Introduction

#packages used
library(haven)
library(tidyverse)
library(zoo)
#Convenience functions 
numextract <- function(string){ 
  as.numeric(str_extract(string, "\\-*\\d+\\.*\\d*"))
} 

comma <- function(x) format(x, digits = 3, big.mark = ",")

comma_2 <- function(x) format(x, digits = 2, big.mark = ",")

This script creates a long form longitudinal dataset which tracks heart transplant candidates (identified by the PX_ID variable) from the time of initial listing until death. It requires the following SRTR Standard Analysis Files (SAF) data files as inputs (SAS format)

  1. “cand_thor.sas7bdat”: Initial candidate registration data
  2. “stathist_thor.sas7bdat”: Candidate status history record
  3. “statjust_hr1a.sas7bdat” and “statjust_hr1b.sas7bdat”: Status 1A and 1B justification forms
  4. “tx_hr.sas7bdat”: Transplant Record
  5. “donor_deceased.sas7bdat”: Detailed data on deceased donors

The script also creates the first paragraph of the results section as well as all the numbers for Figure 1.

Our project used the quarter 3 2018 SAF:


# read in the SRTR SAF files
cand_thor <- read_sas("SAF 2018 Q3/cand_thor.sas7bdat", NULL) %>%  
  zap_formats() %>% zap_labels()

tx_hr <- read_sas("SAF 2018 Q3/tx_hr.sas7bdat", NULL) %>%  
  zap_formats() %>% zap_labels()

stathist_thor <- read_sas("SAF 2018 Q3/stathist_thor.sas7bdat", NULL) %>%  
  zap_formats() %>% zap_labels()

statjust_hr1a <- read_sas("SAF 2018 Q3/statjust_hr1a.sas7bdat", NULL) %>%  
  zap_formats() %>% zap_labels()

statjust_hr1b <- read_sas("SAF 2018 Q3/statjust_hr1b.sas7bdat", NULL) %>% 
  zap_formats() %>% zap_labels()

donor_deceased <- read_sas("SAF 2018 Q3/donor_deceased.sas7bdat", NULL) %>%  
  zap_formats() %>% zap_labels()


institution <- read_sas("SAF 2018 Q3/institution.sas7bdat", NULL) %>%  
  zap_formats() %>% zap_labels()

Filter initial candidate listings according to inclusion/exclusion criterias

Set data range and exclusion criteria

start_year <- 2006
end_year <- 2015
min_tx <- 11 #minimum transplants in entire study period
multi <- FALSE #exclude multi-organ recipients
peds <- FALSE # exclude candidates < 18 at the time of listing

outfile <- paste0("clean_time_series_revise", start_year, "_", end_year, ".csv")

Filter candidate dataset


init_list <- cand_thor %>% 
  mutate(list_date = CAN_LISTING_DT, dead_date = PERS_OPTN_DEATH_DT, rem_dt = CAN_REM_DT) %>% 
  mutate(list_year = format(list_date, "%Y")) %>%
    filter(list_year>=start_year & list_year <=end_year & WL_ORG == "HR")  %>% 
  mutate(status = CAN_INIT_STAT, 
         OPO = CAN_LISTING_OPO_ID,
         date_start = list_date)

#remove peds
if (peds == FALSE){
    init_list <- init_list %>% filter(CAN_AGE_AT_LISTING >17)   
    tot_adults <- nrow(init_list)
}

#remove multiorgan recipients
if (multi == FALSE){

    multi_recips <- tx_hr %>% filter(REC_TX_TY == 2 | REC_TX_TY ==4) %>% select(PX_ID,REC_TX_TY)
  
    n_mults <- nrow(init_list %>% filter(PX_ID %in% multi_recips$PX_ID))
    
    init_list <- init_list %>% filter(!PX_ID %in% multi_recips$PX_ID)

    remove(multi_recips)
}

#remove candidates listed at low volume centers
init_list <- init_list %>% 
  mutate(transplant = ifelse(CAN_REM_CD == 4, 1, 0)) %>%
    group_by(CAN_LISTING_CTR_ID) %>% 
  mutate(tot_tx = sum(transplant, na.rm = TRUE)) %>% ungroup() 


num_all_centers <- length(unique(init_list$CAN_LISTING_CTR_ID))

removed_low_tx <- nrow(init_list %>% filter(tot_tx< min_tx))

init_list <- init_list %>% filter(tot_tx>=min_tx) 

#number of low volume centers
num_low_vol_centers <- num_all_centers - length(unique(init_list$CAN_LISTING_CTR_ID))

Identify last observation date for each candidate

#link to transplant record and 
#identify identify last observation date (death, re-transplant, or last follow-up)
init_list <- 
  init_list %>% left_join(tx_hr %>% select(PX_ID, TFL_LASTATUS, TFL_DEATH_DT, TFL_LAFUDATE), 
                          by = "PX_ID") %>% 
  mutate(
    to_die = case_when(
      CAN_REM_CD %in% c(8, 21)==TRUE ~ 1 ,
      TFL_LASTATUS %in% c("D", "R") ==TRUE ~1,
      is.na(PERS_OPTN_DEATH_DT) == FALSE ~ 1,
      is.na(PERS_SSA_DEATH_DT) == FALSE ~ 1,
      TRUE ~0
  ),
  tfl_date = TFL_LAFUDATE,
  dead_date = case_when(
      is.na(PERS_OPTN_DEATH_DT) == FALSE ~ PERS_OPTN_DEATH_DT,
      TRUE ~ PERS_SSA_DEATH_DT),
  rem_dt = CAN_REM_DT,
  final_dt = case_when(
    is.na(dead_date) == FALSE ~ dead_date,
    is.na(tfl_date) == FALSE ~ tfl_date,
    TRUE ~ rem_dt)
)

#preview data
init_list %>% 
  select(PX_ID, to_die, list_date, final_dt, CAN_REM_CD, 
         rem_dt, REC_TX_DT, TFL_LASTATUS, tfl_date, 
         PERS_OPTN_DEATH_DT, PERS_SSA_DEATH_DT, dead_date) %>% 
  arrange(list_date)

Select Candidate Covariates

Candidate covariates required to assign initial listing status under the three-status system and the six-status system. Additional covariates for revision include Age, gender, BMI, Blood type, Cardiac Diagnosis, and sensitization

init_list <- init_list %>% 
  select(PX_ID, OPO, CAN_LISTING_CTR_ID, status, 
         date_start, list_year, list_date, dead_date, final_dt, to_die,
         CAN_DGN,
         CAN_REM_CD, PERS_OPTN_DEATH_DT, PERS_SSA_DEATH_DT,
         CAN_INIT_STAT,
         CAN_VAD_TY, CAN_VAD1, CAN_VAD2, CAN_IV_INOTROP,
         CAN_IABP, CAN_ECMO, CAN_TAH,
         CAN_CARDIAC_OUTPUT, CAN_CARDIAC_OUTPUT_MEDS, 
         CAN_HGT_CM, CAN_WGT_KG,
         CAN_PCW_MEAN, CAN_PCW_MEAN_MEDS,
         CAN_AGE_AT_LISTING, CAN_GENDER, CAN_BMI, CAN_ABO, CAN_DGN, 
         CAN_PRELIM_XMATCH_REQUEST
    ) %>%
  mutate(age = CAN_AGE_AT_LISTING,
         female = ifelse(CAN_GENDER == "F", 1, 0),
         bmi_low = case_when(
           CAN_BMI < quantile(init_list$CAN_BMI, probs = c(0.25, 0.75), na.rm = TRUE)[[1]] ~ 1,
           is.na(CAN_BMI) == FALSE ~ 0
         ),
         bmi_high = case_when(
           CAN_BMI > quantile(init_list$CAN_BMI, probs = c(0.25, 0.75), na.rm = TRUE)[[2]] ~ 1,
           is.na(CAN_BMI) == FALSE ~ 0
         ),
         blood_type = factor(
           case_when(
             CAN_ABO %in% c("A", "A1", "A2") ~ "A",
             CAN_ABO %in% c("A1B", "A2B") ~ "AB",
             TRUE ~ CAN_ABO)
           ),
        simple_diag = case_when(
          CAN_DGN>999 & CAN_DGN<1007 ~ "Dilated cardiomyopathy, non-ischemic",
          CAN_DGN == 1007 | CAN_DGN ==1200 ~ "Ischemic cardiomyopathy",
          CAN_DGN>1048 & CAN_DGN< 1100 ~ "Restrictive cardiomyopathy",
          TRUE ~ "Other"
        ),
        simple_diag = factor(simple_diag, 
                           levels = c("Dilated cardiomyopathy, non-ischemic", 
                                      "Ischemic cardiomyopathy", 
                                      "Restrictive cardiomyopathy", 
                                      "Other")),
        cross_match = ifelse(CAN_PRELIM_XMATCH_REQUEST == "Y", 1, 0)
  )

table(init_list$blood_type)

    A    AB     B     O 
11258  1368  4029 13074 
remove(cand_thor)

#Select Transplant Recipient and Donor Covariates Keep transplant and Donor variables used in donor risk index score * Donor Age * Donor BUN/Cr * Ischemic time * Race Mismatch

And other recipient covariates to generate table S4 in the supplement (comparison of recipient characteristics at high and low benefit centers)

  1. Renal function
  2. Cardiac diagnosis
  3. History of Cardiac Surgery
  4. Age
  5. Listing Status
  6. Support (MCS)
  7. ICD
  8. BMI
  9. Functional Status
  10. Gender
  11. Race
  12. Hemodynamics (Cardiac index and Pulmonary Wedge pressure)
tx <- tx_hr %>% filter(PX_ID %in% init_list$PX_ID) %>%
    mutate(tx_date= REC_TX_DT,
           tfl_date = TFL_LAFUDATE,
           status = CAN_LAST_STAT) %>% 
    arrange(PX_ID, tx_date)

tx <- tx %>% select(PX_ID, REC_OPO_ID, REC_CTR_ID, DONOR_ID, status, tx_date, CAN_RACE,
    CAN_DIAB_TY, CAN_DIAB,
    REC_CREAT, REC_DIAL,
    REC_DGN, 
    REC_CARDIAC_SURG, 
    REC_VAD_TY, REC_VAD1, REC_VAD2, REC_INOTROP, 
    REC_IABP, REC_ECMO, 
    REC_IMPLANT_DEFIB, 
    REC_BMI,
    REC_FUNCTN_STAT, 
    REC_CARDIAC_OUTPUT, REC_CARDIAC_OUTPUT_MEDS, REC_HGT_CM, REC_WGT_KG,
    REC_PCW_MEAN, REC_PCW_MEAN_MEDS,
    REC_PULM_ART_MEAN, REC_PULM_ART_MEAN_MEDS,
    REC_HR_ISCH,
    TFL_LASTATUS, TFL_LAFUDATE
)


donos <- donor_deceased %>% filter(DONOR_ID %in% tx$DONOR_ID) %>% 
  mutate(DON_BUN = as.integer(DON_BUN), 
         DON_CREAT = as.integer(DON_CREAT))

donos <- donos %>% select(DONOR_ID, DON_OPO_CTR_ID,
  DON_AGE,
    DON_RACE,
    DON_CREAT, DON_BUN
    )

tx <- left_join(tx, donos, by = "DONOR_ID")

tx <- tx %>% mutate(
    white_recip = ifelse(CAN_RACE == 8,1,0),
    white_donor = ifelse(DON_RACE == 8,1,0),
    simple_race = case_when(
        CAN_RACE == 8 ~ "White", 
        CAN_RACE == 16 ~ "Black", 
        CAN_RACE == 2000 ~ "Hispanic", 
        CAN_RACE == 64 ~ "Asian", 
        TRUE ~ "Other"),
    simple_don_race = case_when(
        DON_RACE == 8 ~ "White", 
        DON_RACE == 16 ~ "Black", 
        DON_RACE == 2000 ~ "Hispanic", 
        DON_RACE == 64 ~ "Asian", 
        TRUE ~ "Other"),
    black = ifelse(simple_race == "Black", 1, 0),
    black_don = ifelse(simple_don_race == "Black", 1, 0),
    drs = case_when(
            REC_HR_ISCH/60 < 2 ~ 1,
            REC_HR_ISCH/60 >= 2 & REC_HR_ISCH/60 < 4 ~ 2,
            REC_HR_ISCH/60 >=4 & REC_HR_ISCH/60 < 6 ~ 3,
            REC_HR_ISCH/60 >= 6 & REC_HR_ISCH/60 < 8 ~4,
            TRUE ~ 5
        )+
        case_when(
            DON_AGE >=40 & DON_AGE <50 ~ 3,
            DON_AGE >= 50 ~ 5,
            TRUE ~ 0
        ) +
        case_when(
            (DON_BUN/DON_CREAT) > 30 ~ 3,
            TRUE ~ 0
        ) +
        case_when(
            black != black_don ~ 2,
            TRUE ~ 0
        )
    )

#identify "overtreated" recipients based on recipient hemodynamics. 
tx <- tx %>% mutate(
    bsa = 0.007184*(REC_HGT_CM)^(0.725)*REC_WGT_KG^(0.425),
    recip_pcwp = as.numeric(REC_PCW_MEAN),
    recip_ci = REC_CARDIAC_OUTPUT/bsa,
    iabp_rec_no_shock = case_when(
        recip_pcwp < 15 & REC_IABP ==1 ~ 1,
        recip_ci > 1.8 & REC_CARDIAC_OUTPUT_MEDS == "N" & REC_IABP ==1 ~ 1,
        recip_ci > 2.0 & REC_IABP ==1 ~ 1
        ),
    recip_overtreat = case_when(
        recip_pcwp < 15 & REC_INOTROP ==1 & REC_VAD_TY == 1 ~ 1,
        recip_ci > 1.8 & REC_CARDIAC_OUTPUT_MEDS == "N" & REC_INOTROP ==1 & REC_VAD_TY == 1 ~ 1,
        recip_ci > 2.2 & REC_INOTROP ==1 & REC_VAD_TY == 1~ 1,
        recip_pcwp < 15 & REC_IABP ==1 & REC_VAD_TY == 1 ~ 1,
        recip_ci > 1.8 & REC_CARDIAC_OUTPUT_MEDS == "N" & REC_IABP ==1 & REC_VAD_TY == 1~ 1,
        recip_ci > 2.0 & REC_IABP ==1 & REC_VAD_TY == 1~ 1
    )
)


#remove the race variable to avoid redundancy
tx <- tx %>% select(-CAN_RACE)


remove(tx_hr, donor_deceased, donos)

#preview transplant recipient dataset
tx

Merge data sets to create time series

Filter status history file and select key variables

  • Status 1A = 2010
  • Status 1B = 2020
  • Status 2 = 2030
  • Inactive = 2999
hist <- stathist_thor %>% filter(PX_ID %in% init_list$PX_ID) %>% 
    mutate(date_start = CANHX_BEGIN_DT, 
           date_end = CANHX_END_DT, 
           status = CANHX_STAT_CD, 
           real_status = CANHX_STAT_CD, 
           rem_dt = CAN_REM_DT) %>% 
    arrange(PX_ID, date_start) %>% 
  select(PX_ID, status, real_status, date_start, date_end, rem_dt,  CAN_REM_CD)

hist <- distinct(hist, PX_ID, date_start, .keep_all = TRUE)

remove(stathist_thor)

#preview status history data set
hist

Filter status 1A justification file and select key variables

just_1a <- statjust_hr1a %>% 
  filter(PX_ID %in% init_list$PX_ID)  %>% 
    mutate(date_start = CANHX_CHG_DT, 
        status = CANHX_STAT_CD) %>% 
    arrange(PX_ID, date_start) 

#remove redundant or erroneous justifications
just_1a <- distinct(just_1a) %>% 
  filter(CANHX_FORM_STAT == 4 | CANHX_FORM_STAT == 8) %>% 
  distinct(PX_ID, date_start, .keep_all = TRUE)


#select key variables
just_1a <- just_1a %>% select(PX_ID, CAN_LISTING_CTR_ID, 
  status, date_start, CANHX_STAT_TY, CANHX_FORM_STAT, 
    CANHX_DIALYSIS, CANHX_LAB_SERUM_CREAT, 
    CANHX_ADULT_CRITERIA_A, CANHX_ADULT_CRITERIA_B, 
  CANHX_ADULT_CRITERIA_C, CANHX_ADULT_CRITERIA_D, 
  CANHX_ADULT_CRITERIA_E, CANHX_INTRP_DOBU, CANHX_INTRP_DOPA, CANHX_INTRP_MILRIN,
    CANHX_ADMITTED, 
    CANHX_IABP, CANHX_ECMO, CANHX_LVAD_TYPE, CANHX_VAD, CANHX_TAH, CANHX_RVAD_TYPE,
    CANHX_LAB_BILI, 
    CANHX_CARD_OUTPUT, CANHX_HEMO_CI, CANHX_HEMO_INTRP_OBTAINED, CANHX_HEMO_BSA,
    CANHX_HEMO_PCWP,
    CANHX_HEMO_MPAP,
    CANHX_DEV_MALFUNCTN,
    CANHX_DEV_VENT_ARRYTHM
    )

remove(statjust_hr1a)

just_1a

Filter status 1B justifcation file and select key variables. These forms have a lot less information, mainly just report VAD vs. inotropes

just_1b <- statjust_hr1b %>% filter(PX_ID %in% init_list$PX_ID) %>% 
    mutate(date_start = CANHX_CHG_DT, 
        status = CANHX_STAT_CD, 
        stable_lvad = CANHX_VAD, 
        except_1b =CANHX_CRIT_NOT_MET,
        low_dose_ino = pmax(CANHX_REQUIRE_LOW_INOTROP, CANHX_CONT_IV_INOTROP)
        ) %>% 
    arrange(PX_ID, date_start)


just_1b <- distinct(just_1b) %>% 
  filter(CANHX_FORM_STAT == 4 | CANHX_FORM_STAT == 8) %>%   
  distinct(PX_ID, date_start, .keep_all = TRUE)

just_1b <- just_1b %>% 
  select(PX_ID, CAN_LISTING_CTR_ID, status, date_start, 
    low_dose_ino, stable_lvad, except_1b
    )

remove(statjust_hr1b) 

just_1b

Merge data sets to create time series

#merge with history 
cand_time_series <- init_list %>% 
  mutate(int_form =1, rem_cd = CAN_REM_CD) %>% 
  full_join(hist, c("PX_ID", "date_start", "status"), suffix = c(".init", ".hist")) %>% 
  arrange(PX_ID, date_start)


#merge with 1A justifications, keeping justification forms in the middle of a history period
cand_time_series <- cand_time_series %>% 
  full_join(just_1a, by = c("PX_ID", "date_start", "status"), suffix = c(".init", ".j1a"))  %>% 
  arrange(PX_ID, date_start)

#merge with 1B justiciations, keeping justification forms in the middle of a history period
cand_time_series <- cand_time_series %>% 
  full_join(just_1b, by = c("PX_ID", "date_start", "status"), suffix = c(".init", ".j1b")) %>% 
  arrange(PX_ID, date_start) 

#carryforward "real status" status history dataset
cand_time_series <- cand_time_series %>% arrange(PX_ID, date_start) %>% 
  group_by(PX_ID) %>% 
  mutate(real_status = na.locf(real_status, na.rm = FALSE)) %>% 
  ungroup() 

#remove justification forms that didn't actually change offical status
cand_time_series <- cand_time_series %>% 
  filter(real_status == status | int_form ==1)

Add transplant files to time series


cand_time_series <- cand_time_series %>% 
  mutate(date = date_start)

tx <- tx %>% mutate(date = tx_date)

time_series <- cand_time_series %>% 
  full_join(tx, by = c("PX_ID", "date", "status"), suffix = c(".cand", ".tx")) %>% 
  arrange(PX_ID, date) 


#verify initial status counts are the same (not run)
# init_list %>% count(status)
# cand_time_series %>% filter(int_form==1) %>% count(status)
#time_series %>% filter(int_form==1) %>% count()

There are a total of 165275 observations in the dataset for 29729 candidates listed during the study period. The post-transplant period is considered one observation.

Convert dates to start/stop time in days variables


#carryforward key dates and death status
ts <- time_series %>% ungroup() %>% 
  arrange(PX_ID, date) %>% 
  group_by(PX_ID) %>% 
  mutate(
    tx = if_else(is.na(tx_date)==FALSE, 1, 0), 
    to_die = na.locf(to_die, na.rm = FALSE),
    final_dt = na.locf(final_dt, na.rm = FALSE),
    list_date = na.locf(list_date, na.rm = FALSE)
)


#create time (days) variable
ts <- ts %>% group_by(PX_ID) %>% mutate(
  t_1 = as.numeric(date-list_date),
    last_ob = if_else(row_number()==n(), 1, 0),
  t_2 = ifelse(last_ob ==0, lead(t_1), final_dt - list_date)
) %>% ungroup()


# capture transplant procedure deaths
# This captures hyperacute perioperative risk. Also capture one day listings of any type
ts <- ts %>% 
  mutate( t_2 = ifelse(t_1 == t_2 & tx ==1 & date == final_dt & to_die ==1, t_2 + 1, t_2),
          t_2 = ifelse(t_1 == t_2 & list_date == final_dt & int_form ==1, t_2 + 1, t_2))

#filter out one day periods and erroneous datings 
#(where listing date is after the death date in social security death master file). 
#This erroneous listings are including as in the exclusions in Figure 1)
ts <- ts %>%
  filter(t_2 > t_1) %>% 
  group_by(PX_ID) %>%
  mutate(
    last_ob = if_else(row_number()==n(), 1, 0),
    dead = if_else(last_ob ==1 & to_die ==1, 1, 0)
  ) %>% 
  ungroup()

#preview clean time series data
ts %>% select(PX_ID, status,tx, t_1, t_2, dead, date, list_date, final_dt)

#137 date entry errors below
#ts %>% filter(int_form==1) %>% count()
#create center and OPO variables
ts <- ts %>% mutate(
  center = case_when(
    is.na(CAN_LISTING_CTR_ID.init) == FALSE ~ CAN_LISTING_CTR_ID.init,
    is.na(CAN_LISTING_CTR_ID.j1a) == FALSE ~ CAN_LISTING_CTR_ID.j1a,
    is.na(REC_CTR_ID) == FALSE ~ REC_CTR_ID
    ), 
  center = na.locf(center))

ts <- ts %>% mutate(
  OPO = case_when(
    is.na(REC_OPO_ID) == FALSE ~ REC_OPO_ID,
    TRUE ~ OPO
    ),  OPO = na.locf(OPO))


ts %>% select(PX_ID, center, OPO, status, t_1, t_2, tx, dead)

Code six-status designations

Generate * stat_just, a variable to that identifies three-status justifications and inactive statuses * three_status, a variable that is missing when inactive and just records active three-status * era_tx (transplant year dichotomized) * tx_risky_don (donor risk score > 5) transplant modifying variables

final <- ts %>% 
  mutate(
  stat_just = case_when(
    CANHX_ADULT_CRITERIA_A ==1~ "Status 1A (MCS for shock)",
    CANHX_ADULT_CRITERIA_B == 1 ~ "Status 1A (MCS complication)",
    CANHX_ADULT_CRITERIA_C == 1 ~ "Status 1A (Mechanical ventilation)",
    CANHX_ADULT_CRITERIA_D == 1 ~ "Status 1A (High dose inotropes)",
    CANHX_ADULT_CRITERIA_E == 1 ~ "Status 1A (Exception)",
    status == 2010 & tx == 0 ~ "Status 1A (no justification listed)",
    status == 2010 & tx == 1 & t_1 == 0 ~ "Status 1A (no justification listed)",
    status == 2020 & low_dose_ino ==1  ~ "Status 1B (inotropes)",
    status == 2020 & stable_lvad ==1 ~ "Status 1B (stable VAD)",
    status == 2020 & except_1b ==1 ~ "Status 1B (Exception)",
    status == 2020 & tx == 0 ~ "Status 1B (No justification listed)",
    status == 2030  ~ "Status 2",
    status == 2999 ~ "Inactive"),
  tx_year = as.numeric(format(tx_date, "%Y")),
  era_tx = ifelse((tx_year<=2010) & tx ==1, 1, 0),
  tx_risky_don = if_else(tx ==1 & drs>5, 1, 0),
  three_status = case_when(
    status == 2010 ~ "Status 1A",
    status == 2020 ~ "Status 1B",
    status == 2030 ~ "Status 2"
  )
  )

Identify LVAD complications that are not device malfunctions

final <- final %>% mutate(
  lvad_comp = case_when(
    CANHX_ADULT_CRITERIA_B ==1 & CANHX_DEV_MALFUNCTN ==1 ~ as.numeric(0),
    TRUE ~ as.numeric(CANHX_ADULT_CRITERIA_B)
  )
)

Identify LVAD patients listed with Status 1A elective time

##official SRTR list 
durable_list <- c(205, 206, 208, 210, 216, 217, 223, 224, 230, 231, 232, 233, 
                  305, 306, 313, 316, 319, 325, 402)
lvad_list <- c(205, 206, 208, 210, 216, 217, 223, 224, 230, 231, 232, 233)
final <- final %>%mutate(
  cf_lvad = case_when(
    CANHX_LVAD_TYPE %in% lvad_list ~1,
    CAN_VAD_TY == 2 & CAN_VAD1 %in% lvad_list ~ 1,
    REC_VAD_TY == 2 & REC_VAD1 %in% lvad_list ~ 1,
    CANHX_ADULT_CRITERIA_B==1 ~1,
    status == 2020 & stable_lvad==1 ~ 1
  ),
    elective_1A = case_when(
    CANHX_ADULT_CRITERIA_A ==1 & cf_lvad ==1 & CANHX_IABP ==0 & CANHX_ECMO ==0 ~ 1,
    CANHX_ADULT_CRITERIA_B == 1 ~ 0,
    CANHX_ADULT_CRITERIA_C == 1 ~ 0,
    CANHX_ADULT_CRITERIA_D == 1 ~ 0,
    CANHX_ADULT_CRITERIA_E == 1 ~ 0
    )
) 

Identify time periods when candidate supported with an IABP or multiple inotropes would be downgraded to Status 4 based on cardiac index, pulmonary capillary wedge pressure, or inotrope dose. See supplement for more details

final <- final %>% mutate(
  ino_ci = as.numeric(CANHX_HEMO_CI),
    ino_pcwp = as.numeric(CANHX_HEMO_PCWP),
  n_inos = ifelse(is.na(CANHX_INTRP_DOPA)==FALSE, 1, 0) + 
    ifelse(is.na(CANHX_INTRP_DOBU)==FALSE, 1, 0) + 
    ifelse(is.na(CANHX_INTRP_MILRIN)==FALSE, 1, 0),
  n_inos = ifelse(status != 2010, NA, n_inos),
    multi_ino = ifelse(n_inos > 1, 1, 0),
    single_ino = ifelse(n_inos ==1, 1, 0),
    low_d_ino = ifelse(n_inos> 1 & 
               (CANHX_INTRP_DOPA<3 | CANHX_INTRP_MILRIN <0.25 | CANHX_INTRP_DOBU < 3), 1, 0),
    low_s_ino = ifelse(n_inos ==1 & (CANHX_INTRP_MILRIN <0.5 | CANHX_INTRP_DOBU < 7.5),1,0),
  bsa = 0.007184*(CAN_HGT_CM)^(0.725)*CAN_WGT_KG^(0.425),
  tcr_ci = CAN_CARDIAC_OUTPUT/bsa,
  iabp_no_shock = case_when(
    tcr_ci > 1.8 & CAN_CARDIAC_OUTPUT_MEDS == "N" & (CANHX_IABP==1 | CAN_IABP ==1) ~ 1,
    tcr_ci > 2.0 & (CANHX_IABP==1 | CAN_IABP ==1) ~ 1,
    is.na(tcr_ci) == FALSE & (CANHX_IABP==1 | CAN_IABP ==1) ~ 0
  ),
    overtreat = case_when(
      iabp_rec_no_shock ==1 ~ 1,
        recip_overtreat == 1 ~ 1,
        CAN_PCW_MEAN < 15 & CAN_IABP ==1 ~ 1,
        CANHX_HEMO_PCWP < 15 & CANHX_ADULT_CRITERIA_D ==1 ~ 1,
        ino_ci>2.2~ 1,
        ino_pcwp <15 ~ 1,
        (ino_ci>1.8 & CANHX_HEMO_INTRP_OBTAINED =="N") ~ 1,
        low_d_ino == 1 | low_s_ino == 1 ~ 1, 
        iabp_no_shock == 1 ~ 1,
        ino_ci <= 1.8 ~ 0,
        (ino_ci <= 2.2 & CANHX_HEMO_INTRP_OBTAINED =="Y") ~ 0,
        iabp_no_shock == 0 ~ 0
    ),
  over_1a = ifelse(status == 2020 | status == 2030, 0, overtreat)
)

Code six-status

#non dischargable VADs
non_discharge <- c(201, 203, 204, 209, 215, 218, 221, 222, 225, 226, 227, 228, 
                   234, 301, 302, 303, 309, 310, 311, 320, 321)

#restrictive, amyloid, CHD, and HCOM, cardiomyopathy diagnoses
stat4_diagnoses <- c(1050, 1051, 1052, 1053, 1054, 1099, 1100, 1101, 1102, 
                     1103, 1104, 1105, 1106, 1199, 1200, 1201, 1203, 1205, 1206, 1207, 1208)


final <- final %>% group_by(PX_ID) %>% 
  mutate(diagnosis = na.locf(CAN_DGN, na.rm = FALSE)) %>%
  ungroup()


final <- final %>% mutate(
  six_status = case_when(
    status == 2020~ 4,
    diagnosis %in% stat4_diagnoses & status ==2030 ~ 4,
    status == 2030~ 6,
    overtreat == 1 ~ 4,
    elective_1A ==1 ~ 3,
    lvad_comp ==1 ~3,
    CAN_ECMO == 1 ~1,
    CANHX_ECMO == 1 ~ 1,
    REC_ECMO == 1 ~ 1,
    CANHX_ADULT_CRITERIA_A ==1 & CANHX_RVAD_TYPE %in% non_discharge ~ 1,
    CAN_VAD_TY == 5 & (CAN_VAD1 %in% non_discharge | CAN_VAD2 %in% non_discharge) ~ 1,
    REC_VAD_TY == 5 & (REC_VAD1 %in% non_discharge | REC_VAD2 %in% non_discharge) ~ 1,
    CANHX_ADULT_CRITERIA_A ==1 ~ 2,
    CANHX_DEV_MALFUNCTN ==1  ~ 2,
    CANHX_DEV_VENT_ARRYTHM == 1 ~ 2,
    status == 2010 & tx ==0 ~ 3
  ),
  over_1a = ifelse(six_status != 4, 0, over_1a),
  elective_1A = ifelse(six_status != 3 | status == 2999, 0, elective_1A),
  lvad_comp = ifelse(six_status != 3, 0, lvad_comp)) 

#confirm that the status 2010 patients reassigned to status 4 are all overtreated (not run)
#final %>% filter(six_status ==4 & status ==2010) %>% count(over_1a)

Add LVAD variable

final <- final %>%
  mutate(lvad = case_when(
    lvad_comp ==1 ~ 1,
    elective_1A == 1 ~ 1,
    stable_lvad == 1 ~ 1
  ))

Example data for a patient:

final %>% filter(PX_ID == 531687) %>% 
  select(t_1, t_2, tx, dead, stat_just, six_status, 
         over_1a, lvad_comp, elective_1A)

This patient went through the following status changes:

  • status 1B with IV inotropes (day 0-35)
  • status 1A exception (coded as six-status 3) (day 36-41)
  • status 1B with IV inotropes (day 42-140)
  • status 1A with high dose IV inotropes (remained six-status 4 due to lack of cardiogenic shock) (day 141-148)
  • Inactivated (day 150-177)
  • re-activated at Status 1A s/p durable LVAD implantation with elective time (six-status 3) (day 178-181)
  • Inactivated (day 182-197)
  • re-activated at Status 1A w/ LVAD complication (not device failure, so six-status 3) (day 198-208)
  • transplanted and survived for over ten years (day 209- 3863)

When the candidate is inactivated from the list, we carry forward their status from the previous observed period. Because many candidates are deactivated from list before dying, this assumption allows the model to appropriately capture the risk of each active waitlist status.

#carry forward statuses to fill inactive periods
data <- final %>% 
  arrange(PX_ID, t_1) %>% group_by(PX_ID) %>% 
  mutate_at(vars(six_status, stat_just, three_status, 
                 over_1a, list_year, 
                 lvad_comp, elective_1A, cf_lvad, 
                 blood_type, age, female, bmi_low, 
                 bmi_high, simple_diag, cross_match), 
            list(~na.locf(., na.rm = FALSE))) %>% 
  ungroup()

Example data for a patient with statuses “carried forward”

data %>% filter(PX_ID == 531687) %>% 
  select(t_1, t_2, tx, dead, 
         stat_just, six_status, over_1a, 
         lvad_comp, elective_1A, cf_lvad, 
         age, female, black, 
         bmi_low, bmi_high, diagnosis, cross_match)
data %>% select(PX_ID, t_1, t_2, tx, dead, stat_just, cf_lvad)

For the 198 recipients with only one observation, assign them status three for 1A, four for 1B, and six for 2.

data <- data %>%
  mutate(
    six_status = case_when(
      tx ==1 & is.na(six_status) & three_status == "Status 1A" ~ 3,
      tx ==1 & is.na(six_status) & three_status == "Status 1B" ~ 4,
      tx ==1 & is.na(six_status) & three_status == "Status 2" ~ 6,
      TRUE ~ six_status
    )
  )
#dummy code statuses
data <- data %>%
  mutate(
    stat_1a = ifelse(three_status == "Status 1A", 1, 0),
    stat_1b = ifelse(three_status =="Status 1B", 1,0),
    stat_2 = ifelse(three_status == "Status 2", 1, 0), 
    status_1 = ifelse(six_status == 1, 1, 0),
    status_2 = ifelse(six_status == 2, 1, 0),
    status_3 = ifelse(six_status == 3, 1, 0),
    status_4 = ifelse(six_status == 4, 1, 0),
    status_6 = ifelse(six_status == 6, 1, 0)
  )

Create analytic dataset for the model and write out as csv file

to_model <- data %>% 
  select(PX_ID, center, OPO, t_1, t_2, tx, dead, stat_1a, stat_1b, stat_2, 
         status_1, status_2, status_3, status_4, status_6, 
         stat_just, three_status, six_status,
         cf_lvad,
         era_tx, tx_risky_don,
         DON_BUN, DON_CREAT, DON_AGE, REC_HR_ISCH, 
         black, black_don,
         list_year,
         age, female, blood_type, bmi_low, bmi_high, simple_diag, cross_match) %>%
  mutate_at(vars(cf_lvad, black, black_don, REC_HR_ISCH, DON_BUN, DON_CREAT, DON_AGE), 
            list(~ifelse(is.na(.)==TRUE, 0, .)))%>%
  drop_na(stat_1a) ##Key filter step, removes patients who were never activated

# not run- confirm dropped patients were never activated on the waitlist
# data %>% 
#   group_by(PX_ID) %>%
#   count(stat_just) %>%
#   mutate(total_justs = sum(n)) %>%
#   spread(key = stat_just, value = n) %>%
#   filter(total_justs == Inactive)
center_region <- institution %>% 
  filter(CTR_TY %in% c("TX1", "VA1", "FTX")) %>% 
  select(CTR_ID, REGION) %>%
  rename(center= CTR_ID)

to_model <- to_model %>% left_join(center_region, by = "center")
Column `center` has different attributes on LHS and RHS of join
#write final data set out as a csv file
write_csv(to_model, outfile)

Six-status system coding summary for all observations

ftable(to_model$stat_just, to_model$six_status)
                                         1     2     3     4     6
                                                                  
Inactive                               198  1032  2463 10001  3491
Status 1A (Exception)                   23     0  4975   271     0
Status 1A (High dose inotropes)         12     0  8607 19543     0
Status 1A (MCS complication)            51  4006 28305    43     0
Status 1A (MCS for shock)              866  6585 10722  1237     0
Status 1A (Mechanical ventilation)      50     0  1036    28     1
Status 1A (no justification listed)      2     0   130     3     0
Status 1B (Exception)                    0     0     0  1962     0
Status 1B (inotropes)                    0     0     0 22621     0
Status 1B (No justification listed)      0     0     0  4029     0
Status 1B (stable VAD)                   0     0     0 15907     0
Status 2                                 0     0     0  3076 11964

Note: The candidates with exceptions, high dose inotropes, or mechanical ventilation who MCS complications who were coded as Status 1 met the criteria because had a MCSD with life-threatening ventricular arrhythmia, or were supported by VA ECMO or Non-dischargeable, surgically implanted, non-endovascular bi-ventricular support device.

##Six-status system coding summary for all recipients

recips <- to_model %>% filter(tx ==1)
ftable(recips$stat_just, recips$six_status)
                                        1    2    3    4    6
                                                             
Status 1A (Exception)                  17    0  610  266    0
Status 1A (High dose inotropes)         8    0  711 2634    0
Status 1A (MCS complication)           51  422 2567   40    0
Status 1A (MCS for shock)             171  832 2337  620    0
Status 1A (Mechanical ventilation)      6    0   27   17    1
Status 1A (no justification listed)     2    0    3    0    0
Status 1B (Exception)                   0    0    0  502    0
Status 1B (inotropes)                   0    0    0 4336    0
Status 1B (No justification listed)     0    0    0  637    0
Status 1B (stable VAD)                  0    0    0 1660    0
Status 2                                0    0    0  288 1050
ftable(recips$six_status, recips$three_status)
   Status 1A Status 1B Status 2
                               
1        255         0        0
2       1254         0        0
3       6255         0        0
4       3462      7250      288
6          1         0     1050
to_model %>% select(PX_ID, t_1, t_2, tx, dead, stat_just, cf_lvad)

Results: Study Population



#calculate values for flow-chart
tot_analyzed <- to_model %>% group_by(PX_ID) %>% filter(row_number()==1) %>% ungroup() %>% nrow()

miss_data <- nrow(init_list) - tot_analyzed

#missing data exclusion detail
total_exclusions <- tot_adults - tot_analyzed


##identify candidates who were never active
only_inactive <- data %>% 
  group_by(PX_ID) %>% summarise(mean_stat = min(status)) %>% 
  filter(mean_stat == 2999) %>% ungroup() %>% nrow()

##remaining candidates had erroneous dates
error_dates <- init_list %>% filter(!PX_ID %in% data$PX_ID)
error_dates <- length(unique(error_dates$PX_ID))


#outcomes

##total deaths without transplant
died_before_tx <- to_model %>% 
  group_by(PX_ID) %>% 
  filter(row_number()== n()) %>% 
  ungroup() %>% 
  filter(tx ==0 & dead ==1) %>% nrow()

##deaths while still active on list
death_on_list <- data %>% 
  filter(PX_ID %in% to_model$PX_ID) %>% 
  group_by(PX_ID) %>% 
  filter(row_number()==1) %>% 
  ungroup() %>% 
  filter(CAN_REM_CD.init == 8) %>%
  nrow()

##deaths after delisting
died_delist <- died_before_tx - death_on_list

##transplanted
tot_tx <- recips %>% nrow()

##still waiting at end of follow-up
still_waiting <-tot_analyzed - tot_tx - died_before_tx

#Post-transplant outcomes
##dead or re-transplanted post-transplant
dead_post_tx <- recips %>% filter(dead ==1) %>% nrow()

##re-transplant
post_tx_re_tx <- data %>% 
  filter(PX_ID %in% to_model$PX_ID) %>% 
  group_by(PX_ID) %>% 
  filter(tx == 1) %>% 
  ungroup() %>% 
  filter(TFL_LASTATUS == "R") %>%
  nrow()

##deaths
post_tx_deaths <- dead_post_tx - post_tx_re_tx

##alive post-transplant
alive_post_tx <- recips %>% filter(dead == 0) %>% nrow()


##calculate mean follow-up time for censored observations
last_ob <- to_model %>% 
  group_by(PX_ID) %>% arrange(t_1) %>% 
  filter(dead ==0 & row_number() == n()) %>% 
  select(PX_ID, t_2)

mean_fup_time <- comma_2(mean(last_ob$t_2)/365)

During 2006-2015, there were 30,899 adult candidates registered for heart transplantation in the US. After exclusions (Figure 1), the remaining eligible 29,199 adult candidates were listed at 113 centers and 19,815 (68%) received a heart transplant. Among heart transplant recipients, 5,389 (27%) died or were re-transplanted during the study period and 14,426 (73%) remained alive at last follow-up. Of the 9,384 candidates who did not receive a transplant, 5,669 (60%) died (2,644 while on the waitlist and 3,025 after delisting) and 3,715 (40%) were alive but had not received a transplant by the end of follow-up. Surviving patients in the cohort were followed for an average of 5.4 years before censoring.

Figure 1: STROBE flow diagram

Study population selection displayed in STrengthening the Reporting of OBservational studies in Epidemiology (STROBE) diagram format. We excluded 970 for multi-organ transplantation, 200 candidates for listing at one of 33 low volume centers, 393 candidates who were never activated on the list, and 137 candidates with obvious data entry.

  • There were 30,899 adult heart transplant candidates listed from 2006-2015
  • After applying exclusion criteria, the total number of candidates analyzed was 29,199
  • There were 1,700 Exclusions
    • multi-organ transplant 970
    • low-volume center 200
    • missing data 530
      • 393 exclusions for candidates who were never activated on the list
      • 137 candidates with obvious date data entry errors
  • A total of 9,384 candidates were not transplanted
    • 5,669 candidates died before transplant
      • death on waitlist (N= 2,644)
      • died after delisting (N = 3,025)
    • 3,715 candidates did not receive a transplant before the end of follow-up
  • There were 19,815 total transplants
    • A total of 5,389 recipients died or were re-transplanted
      • post-transplant death (N = 5,204)
      • re-transplant(N = 185)
    • The remaining 14,426 recipients remained alive at last follow-up

Table 1

library(tableone)

cand_thor <- read_sas("SAF 2018 Q3/cand_thor.sas7bdat", NULL) %>%  
  zap_formats() %>% zap_labels()

for_table_one <- to_model %>% 
  group_by(PX_ID) %>%
  mutate(tx_mean = mean(tx),
         got_tx = ifelse(tx_mean> 0, 1, 0)) %>%
  filter(row_number()==1) %>%
  ungroup() %>%
  left_join(cand_thor)
Joining, by = "PX_ID"
Column `PX_ID` has different attributes on LHS and RHS of join
for_table_one <- for_table_one %>%
  select(
    CAN_AGE_AT_LISTING,
    CAN_GENDER,
    CAN_BMI,
    CAN_RACE,
    CAN_DGN,
    CAN_ABO,
    CAN_DIAB_TY,
    CAN_MOST_RECENT_CREAT,
    CAN_DIAL,
    CAN_FUNCTN_STAT,
    CAN_PCW_MEAN,
    CAN_PULM_ART_MEAN,
    CAN_CARDIAC_OUTPUT,
    CAN_WGT_KG,
    CAN_HGT_CM,
    CAN_PRIMARY_PAY,
    stat_just,
    cf_lvad,
    got_tx) %>%
   mutate(Gender = factor(CAN_GENDER, levels = c("F", "M")),
         Race = factor(CAN_RACE),
         Race = fct_lump(Race, n = 3),
        Race = fct_recode(Race,
                          "White" = "8",
                          "Black" = "16",
                          "Hispanic" = "2000", 
                          "Other" = "Other"),
        Diagnosis = case_when(
          CAN_DGN>999 & CAN_DGN<1007 ~ "Dilated cardiomyopathy, non-ischemic",
          CAN_DGN == 1007 | CAN_DGN ==1200 ~ "Ischemic cardiomyopathy",
          CAN_DGN>1048 & CAN_DGN< 1100 ~ "Restrictive cardiomyopathy",
          TRUE ~ "Other"
        ),
        Diagnosis = factor(Diagnosis, 
                           levels = c("Dilated cardiomyopathy, non-ischemic", 
                                      "Ischemic cardiomyopathy", 
                                      "Restrictive cardiomyopathy", 
                                      "Other")),
        Diabetes = case_when(
          CAN_DIAB_TY>1 & CAN_DIAB_TY<6 ~ "History of DM",
          CAN_DIAB_TY ==1 ~ "Non-diabetic",
          TRUE ~ "Unknown"
        ),
        female_gfr = if_else(CAN_GENDER == "F", 0.742, 1),
        black_gfr = if_else(Race == "Black", 1.21, 1),
eGFR = 175*((CAN_MOST_RECENT_CREAT)^(-1.154))*(CAN_AGE_AT_LISTING^(-0.203))*female_gfr*black_gfr,
        Renal_Function = case_when(
          CAN_DIAL == "Y" ~ "Dialysis",
          eGFR >= 60 ~ "GFR >= 60 ml/min/1.73 m^2",
          eGFR>= 30 ~ "GFR >= 30 & <60 ml/min/1.73 m^2",
          eGFR < 30 ~ "GFR < 30 ml/min/1.73 m^2",
          TRUE ~ "Unknown"
        ),
        Renal_Function = if_else(is.na(Renal_Function)==TRUE, "Unknown", Renal_Function),
        body_surface_area = 0.007184*(CAN_HGT_CM)^(0.725)*CAN_WGT_KG^(0.425),
        Cardiac_Index = as.numeric(CAN_CARDIAC_OUTPUT/body_surface_area),
        Functional_Status = case_when(
          CAN_FUNCTN_STAT == 1 | (CAN_FUNCTN_STAT>2069) ~"Limited Impairment, 10-30%",
          (CAN_FUNCTN_STAT>2039 & CAN_FUNCTN_STAT<2061) ~ "Moderate Impairment, 40-60%",
          (CAN_FUNCTN_STAT>2000 & CAN_FUNCTN_STAT<2031) ~ "Severe Impairment, 70-100%",
          TRUE ~ "Unknown"
        ),
        Functional_Status = ifelse(is.na(Functional_Status), "Unknown", Functional_Status),
        severe_impairment = ifelse(Functional_Status == "Severe Impairment, 70-100%", 1, 0),
        acute_mcs = ifelse(stat_just == "Status 1A (MCS for shock)", 1, 0),
        lvad_comp = ifelse(stat_just == "Status 1A (MCS complication)", 1, 0),
        pcwp_15 = ifelse(CAN_PCW_MEAN < 15, 1, 0),
        pcwp_15 = ifelse(is.na(CAN_PCW_MEAN), 0, pcwp_15),
         blood_type = factor(
           case_when(
             CAN_ABO %in% c("A", "A1", "A2") ~ "A",
             CAN_ABO %in% c("A1B", "A2B") ~ "AB",
             TRUE ~ CAN_ABO)
           ),
        payor = case_when(
          CAN_PRIMARY_PAY %in% c(3,4,13) ~ "Medicare",
          CAN_PRIMARY_PAY ==2 ~ "Medicaid",
          CAN_PRIMARY_PAY == 1 ~ "Private",
          TRUE ~ "Other"
        )
  )

library(tableone)
cont_vars <- c("CAN_AGE_AT_LISTING", "CAN_BMI", 
               "CAN_PULM_ART_MEAN", "CAN_PCW_MEAN", "Cardiac_Index")

cat_vars <- c( "stat_just", "cf_lvad", 
               "Gender","Race", 
               "Diagnosis", "Diabetes", "Renal_Function", 
               "Functional_Status","severe_impairment", 
               "acute_mcs", "lvad_comp", "pcwp_15", "blood_type", "payor")



CreateTableOne(vars=cont_vars, data = for_table_one, strata = "got_tx")
                                Stratified by got_tx
                                 0             1             p      test
  n                               9384         19815                    
  CAN_AGE_AT_LISTING (mean (SD)) 52.35 (12.58) 52.39 (12.49)  0.768     
  CAN_BMI (mean (SD))            28.35 (5.30)  27.19 (4.99)  <0.001     
  CAN_PULM_ART_MEAN (mean (SD))  30.27 (10.90) 29.85 (10.17)  0.002     
  CAN_PCW_MEAN (mean (SD))       19.97 (8.85)  20.19 (8.73)   0.058     
  Cardiac_Index (mean (SD))       2.20 (0.66)   2.16 (0.65)  <0.001     
cat_vars_by_tx <- print(CreateCatTable(vars = cat_vars, data = for_table_one, strata = "got_tx"))
                                         Stratified by got_tx
                                          0            1             p      test
  n                                       9384         19815                    
  stat_just (%)                                                      <0.001     
     Status 1A (Exception)                  88 ( 0.9)    264 ( 1.3)             
     Status 1A (High dose inotropes)       595 ( 6.3)   2021 (10.2)             
     Status 1A (MCS complication)          145 ( 1.5)    426 ( 2.1)             
     Status 1A (MCS for shock)             965 (10.3)   2394 (12.1)             
     Status 1A (Mechanical ventilation)    117 ( 1.2)     92 ( 0.5)             
     Status 1A (no justification listed)    11 ( 0.1)     11 ( 0.1)             
     Status 1B (Exception)                  89 ( 0.9)    234 ( 1.2)             
     Status 1B (inotropes)                2251 (24.0)   6064 (30.6)             
     Status 1B (No justification listed)     0 ( 0.0)      2 ( 0.0)             
     Status 1B (stable VAD)               1046 (11.1)   2428 (12.3)             
     Status 2                             4077 (43.4)   5879 (29.7)             
  cf_lvad = 1 (%)                         1710 (18.2)   4617 (23.3)  <0.001     
  Gender = M (%)                          6946 (74.0)  14795 (74.7)   0.243     
  Race (%)                                                           <0.001     
     White                                6193 (66.0)  13362 (67.4)             
     Black                                2201 (23.5)   4046 (20.4)             
     Hispanic                              689 ( 7.3)   1562 ( 7.9)             
     Other                                 301 ( 3.2)    845 ( 4.3)             
  Diagnosis (%)                                                      <0.001     
     Dilated cardiomyopathy, non-ischemic 3651 (38.9)   8688 (43.8)             
     Ischemic cardiomyopathy              3499 (37.3)   7382 (37.3)             
     Restrictive cardiomyopathy            907 ( 9.7)   1866 ( 9.4)             
     Other                                1327 (14.1)   1879 ( 9.5)             
  Diabetes (%)                                                       <0.001     
     History of DM                        2950 (31.4)   5442 (27.5)             
     Non-diabetic                         6398 (68.2)  14331 (72.3)             
     Unknown                                36 ( 0.4)     42 ( 0.2)             
  Renal_Function (%)                                                 <0.001     
     GFR < 30 ml/min/1.73 m^2              833 ( 8.9)    623 ( 3.1)             
     GFR >= 30 & <60 ml/min/1.73 m^2      3792 (40.4)   7811 (39.4)             
     GFR >= 60 ml/min/1.73 m^2            4704 (50.1)  11306 (57.1)             
     Unknown                                55 ( 0.6)     75 ( 0.4)             
  Functional_Status (%)                                              <0.001     
     Limited Impairment, 10-30%           3203 (34.1)   6374 (32.2)             
     Moderate Impairment, 40-60%          3093 (33.0)   7044 (35.5)             
     Severe Impairment, 70-100%           2828 (30.1)   5990 (30.2)             
     Unknown                               260 ( 2.8)    407 ( 2.1)             
  severe_impairment = 1 (%)               2828 (30.1)   5990 (30.2)   0.882     
  acute_mcs = 1 (%)                        965 (10.3)   2394 (12.1)  <0.001     
  lvad_comp = 1 (%)                        145 ( 1.5)    426 ( 2.1)   0.001     
  pcwp_15 = 1 (%)                         2416 (25.7)   4861 (24.5)   0.026     
  blood_type (%)                                                     <0.001     
     A                                    3006 (32.0)   8067 (40.7)             
     AB                                    247 ( 2.6)   1098 ( 5.5)             
     B                                    1058 (11.3)   2899 (14.6)             
     O                                    5073 (54.1)   7751 (39.1)             
  payor (%)                                                          <0.001     
     Medicaid                             1124 (12.0)   2333 (11.8)             
     Medicare                             3155 (33.6)   5816 (29.4)             
     Other                                 390 ( 4.2)    868 ( 4.4)             
     Private                              4715 (50.2)  10798 (54.5)             
write.csv(cat_vars_by_tx, "cat_vars_by_tx.csv")


cont_vars_by_tx <- print(CreateContTable(vars = cont_vars, data = for_table_one, strata = "got_tx"))
                                Stratified by got_tx
                                 0             1             p      test
  n                              9384          19815                    
  CAN_AGE_AT_LISTING (mean (SD)) 52.35 (12.58) 52.39 (12.49)  0.768     
  CAN_BMI (mean (SD))            28.35 (5.30)  27.19 (4.99)  <0.001     
  CAN_PULM_ART_MEAN (mean (SD))  30.27 (10.90) 29.85 (10.17)  0.002     
  CAN_PCW_MEAN (mean (SD))       19.97 (8.85)  20.19 (8.73)   0.058     
  Cardiac_Index (mean (SD))       2.20 (0.66)   2.16 (0.65)  <0.001     
write.csv(cont_vars_by_tx, "cont_vars_by_tx.csv")



cat_vars_ <- print(CreateCatTable(vars = cat_vars, data = for_table_one))
                                         
                                          Overall      
  n                                       29199        
  stat_just (%)                                        
     Status 1A (Exception)                  352 ( 1.2) 
     Status 1A (High dose inotropes)       2616 ( 9.0) 
     Status 1A (MCS complication)           571 ( 2.0) 
     Status 1A (MCS for shock)             3359 (11.5) 
     Status 1A (Mechanical ventilation)     209 ( 0.7) 
     Status 1A (no justification listed)     22 ( 0.1) 
     Status 1B (Exception)                  323 ( 1.1) 
     Status 1B (inotropes)                 8315 (28.5) 
     Status 1B (No justification listed)      2 ( 0.0) 
     Status 1B (stable VAD)                3474 (11.9) 
     Status 2                              9956 (34.1) 
  cf_lvad = 1 (%)                          6327 (21.7) 
  Gender = M (%)                          21741 (74.5) 
  Race (%)                                             
     White                                19555 (67.0) 
     Black                                 6247 (21.4) 
     Hispanic                              2251 ( 7.7) 
     Other                                 1146 ( 3.9) 
  Diagnosis (%)                                        
     Dilated cardiomyopathy, non-ischemic 12339 (42.3) 
     Ischemic cardiomyopathy              10881 (37.3) 
     Restrictive cardiomyopathy            2773 ( 9.5) 
     Other                                 3206 (11.0) 
  Diabetes (%)                                         
     History of DM                         8392 (28.7) 
     Non-diabetic                         20729 (71.0) 
     Unknown                                 78 ( 0.3) 
  Renal_Function (%)                                   
     GFR < 30 ml/min/1.73 m^2              1456 ( 5.0) 
     GFR >= 30 & <60 ml/min/1.73 m^2      11603 (39.7) 
     GFR >= 60 ml/min/1.73 m^2            16010 (54.8) 
     Unknown                                130 ( 0.4) 
  Functional_Status (%)                                
     Limited Impairment, 10-30%            9577 (32.8) 
     Moderate Impairment, 40-60%          10137 (34.7) 
     Severe Impairment, 70-100%            8818 (30.2) 
     Unknown                                667 ( 2.3) 
  severe_impairment = 1 (%)                8818 (30.2) 
  acute_mcs = 1 (%)                        3359 (11.5) 
  lvad_comp = 1 (%)                         571 ( 2.0) 
  pcwp_15 = 1 (%)                          7277 (24.9) 
  blood_type (%)                                       
     A                                    11073 (37.9) 
     AB                                    1345 ( 4.6) 
     B                                     3957 (13.6) 
     O                                    12824 (43.9) 
  payor (%)                                            
     Medicaid                              3457 (11.8) 
     Medicare                              8971 (30.7) 
     Other                                 1258 ( 4.3) 
     Private                              15513 (53.1) 
write.csv(cat_vars_, "cat_vars_.csv")


cont_vars_ <- print(CreateContTable(vars = cont_vars, data = for_table_one))
                                
                                 Overall      
  n                              29199        
  CAN_AGE_AT_LISTING (mean (SD)) 52.38 (12.52)
  CAN_BMI (mean (SD))            27.56 (5.12) 
  CAN_PULM_ART_MEAN (mean (SD))  29.98 (10.41)
  CAN_PCW_MEAN (mean (SD))       20.12 (8.77) 
  Cardiac_Index (mean (SD))       2.17 (0.65) 
write.csv(cont_vars_, "cont_vars_.csv")
LS0tCnRpdGxlOiBEYXRhIHByZXBhcmF0aW9uIGZvciAiQXNzb2NpYXRpb24gb2YgdHJhbnNwbGFudCBjZW50ZXIgd2l0aCBzdXJ2aXZhbCBiZW5lZml0IGFtb25nIGFkdWx0cyB1bmRlcmdvaW5nIGhlYXJ0IHRyYW5zcGxhbnRhdGlvbiBpbiB0aGUgVW5pdGVkIFN0YXRlcyIKYXV0aG9yOiBXaWxsaWFtIEYuIFBhcmtlciBNRCwgTVMsIEFsbGVuIFMuIEFuZGVyc29uIE1ELCBSb2JlcnQgRC4gR2liYm9ucyBQaEQsIEVkd2FyZAogIFIgR2Fycml0eSBKciBNRCwgTGFpbmllIEYgUm9zcywgRWxiZXJ0IFMuIEh1YW5nIE1ELCBhbmQgTWF0dGhldyBNLiBDaHVycGVrIE1ELCBQaEQKZGF0ZTogMTAvMS8yMDE5Cm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnMicKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IGpvdXJuYWwKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDIKICAgIHRvY19mbG9hdDogeWVzCi0tLQoKYGBge3IgZ2xvYmFsX29wdGlvbnMsIGluY2x1ZGUgPSBGQUxTRX0KbGlicmFyeShrbml0cikKCiNzZXQgZ2xvYmFsIG9wdGlvbnMgZm9yIHRoaXMgcm1hcmtkb3duIGRvY3VtZW50Cm9wdHNfY2h1bmskc2V0KGNhY2hlID0gVFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgdGlkeS5vcHRzPWxpc3Qod2lkdGguY3V0b2ZmPTYwKSkKYGBgCgpccGFnZWJyZWFrCgojIEludHJvZHVjdGlvbgpgYGB7ciBwYWNrYWdlcywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGUgPSBGQUxTRX0KI3BhY2thZ2VzIHVzZWQKbGlicmFyeShoYXZlbikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoem9vKQpgYGAKCgpgYGB7ciBmdW5jdGlvbnN9CiNDb252ZW5pZW5jZSBmdW5jdGlvbnMgCm51bWV4dHJhY3QgPC0gZnVuY3Rpb24oc3RyaW5nKXsgCiAgYXMubnVtZXJpYyhzdHJfZXh0cmFjdChzdHJpbmcsICJcXC0qXFxkK1xcLipcXGQqIikpCn0gCgpjb21tYSA8LSBmdW5jdGlvbih4KSBmb3JtYXQoeCwgZGlnaXRzID0gMywgYmlnLm1hcmsgPSAiLCIpCgpjb21tYV8yIDwtIGZ1bmN0aW9uKHgpIGZvcm1hdCh4LCBkaWdpdHMgPSAyLCBiaWcubWFyayA9ICIsIikKYGBgCgoKVGhpcyBzY3JpcHQgY3JlYXRlcyBhIGxvbmcgZm9ybSBsb25naXR1ZGluYWwgZGF0YXNldCB3aGljaCB0cmFja3MgaGVhcnQgdHJhbnNwbGFudCBjYW5kaWRhdGVzIChpZGVudGlmaWVkIGJ5IHRoZSAqKlBYX0lEKiogdmFyaWFibGUpIGZyb20gdGhlIHRpbWUgb2YgaW5pdGlhbCBsaXN0aW5nIHVudGlsIGRlYXRoLiBJdCByZXF1aXJlcyB0aGUgZm9sbG93aW5nIFNSVFIgU3RhbmRhcmQgQW5hbHlzaXMgRmlsZXMgKFNBRikgZGF0YSBmaWxlcyBhcyBpbnB1dHMgKFNBUyBmb3JtYXQpCgoxLiAiY2FuZF90aG9yLnNhczdiZGF0IjogSW5pdGlhbCBjYW5kaWRhdGUgcmVnaXN0cmF0aW9uIGRhdGEKMi4gInN0YXRoaXN0X3Rob3Iuc2FzN2JkYXQiOiBDYW5kaWRhdGUgc3RhdHVzIGhpc3RvcnkgcmVjb3JkCjMuICJzdGF0anVzdF9ocjFhLnNhczdiZGF0IiBhbmQgInN0YXRqdXN0X2hyMWIuc2FzN2JkYXQiOiBTdGF0dXMgMUEgYW5kIDFCIGp1c3RpZmljYXRpb24gZm9ybXMKNC4gInR4X2hyLnNhczdiZGF0IjogVHJhbnNwbGFudCBSZWNvcmQKNS4gImRvbm9yX2RlY2Vhc2VkLnNhczdiZGF0IjogRGV0YWlsZWQgZGF0YSBvbiBkZWNlYXNlZCBkb25vcnMKCgpUaGUgc2NyaXB0IGFsc28gY3JlYXRlcyB0aGUgZmlyc3QgcGFyYWdyYXBoIG9mIHRoZSByZXN1bHRzIHNlY3Rpb24gYXMgd2VsbCBhcyBhbGwgdGhlIG51bWJlcnMgZm9yIEZpZ3VyZSAxLgoKT3VyIHByb2plY3QgdXNlZCB0aGUgcXVhcnRlciAzIDIwMTggU0FGOgpgYGB7ciByZWFkX2luX1NBU30KCiMgcmVhZCBpbiB0aGUgU1JUUiBTQUYgZmlsZXMKY2FuZF90aG9yIDwtIHJlYWRfc2FzKCJTQUYgMjAxOCBRMy9jYW5kX3Rob3Iuc2FzN2JkYXQiLCBOVUxMKSAlPiUgIAogIHphcF9mb3JtYXRzKCkgJT4lIHphcF9sYWJlbHMoKQoKdHhfaHIgPC0gcmVhZF9zYXMoIlNBRiAyMDE4IFEzL3R4X2hyLnNhczdiZGF0IiwgTlVMTCkgJT4lICAKICB6YXBfZm9ybWF0cygpICU+JSB6YXBfbGFiZWxzKCkKCnN0YXRoaXN0X3Rob3IgPC0gcmVhZF9zYXMoIlNBRiAyMDE4IFEzL3N0YXRoaXN0X3Rob3Iuc2FzN2JkYXQiLCBOVUxMKSAlPiUgIAogIHphcF9mb3JtYXRzKCkgJT4lIHphcF9sYWJlbHMoKQoKc3RhdGp1c3RfaHIxYSA8LSByZWFkX3NhcygiU0FGIDIwMTggUTMvc3RhdGp1c3RfaHIxYS5zYXM3YmRhdCIsIE5VTEwpICU+JSAgCiAgemFwX2Zvcm1hdHMoKSAlPiUgemFwX2xhYmVscygpCgpzdGF0anVzdF9ocjFiIDwtIHJlYWRfc2FzKCJTQUYgMjAxOCBRMy9zdGF0anVzdF9ocjFiLnNhczdiZGF0IiwgTlVMTCkgJT4lIAogIHphcF9mb3JtYXRzKCkgJT4lIHphcF9sYWJlbHMoKQoKZG9ub3JfZGVjZWFzZWQgPC0gcmVhZF9zYXMoIlNBRiAyMDE4IFEzL2Rvbm9yX2RlY2Vhc2VkLnNhczdiZGF0IiwgTlVMTCkgJT4lICAKICB6YXBfZm9ybWF0cygpICU+JSB6YXBfbGFiZWxzKCkKCgppbnN0aXR1dGlvbiA8LSByZWFkX3NhcygiU0FGIDIwMTggUTMvaW5zdGl0dXRpb24uc2FzN2JkYXQiLCBOVUxMKSAlPiUgIAogIHphcF9mb3JtYXRzKCkgJT4lIHphcF9sYWJlbHMoKQpgYGAKClxwYWdlYnJlYWsKCiMgRmlsdGVyIGluaXRpYWwgY2FuZGlkYXRlIGxpc3RpbmdzIGFjY29yZGluZyB0byBpbmNsdXNpb24vZXhjbHVzaW9uIGNyaXRlcmlhcwoKU2V0IGRhdGEgcmFuZ2UgYW5kIGV4Y2x1c2lvbiBjcml0ZXJpYQpgYGB7ciBhc3NpZ25fZGF0YV9yYW5nZX0Kc3RhcnRfeWVhciA8LSAyMDA2CmVuZF95ZWFyIDwtIDIwMTUKbWluX3R4IDwtIDExICNtaW5pbXVtIHRyYW5zcGxhbnRzIGluIGVudGlyZSBzdHVkeSBwZXJpb2QKbXVsdGkgPC0gRkFMU0UgI2V4Y2x1ZGUgbXVsdGktb3JnYW4gcmVjaXBpZW50cwpwZWRzIDwtIEZBTFNFICMgZXhjbHVkZSBjYW5kaWRhdGVzIDwgMTggYXQgdGhlIHRpbWUgb2YgbGlzdGluZwoKb3V0ZmlsZSA8LSBwYXN0ZTAoImNsZWFuX3RpbWVfc2VyaWVzX3JldmlzZSIsIHN0YXJ0X3llYXIsICJfIiwgZW5kX3llYXIsICIuY3N2IikKYGBgCgpGaWx0ZXIgY2FuZGlkYXRlIGRhdGFzZXQKYGBge3IgZGF0ZV9yYW5nZV9zZWxlY3QsIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nID0gRkFMU0V9Cgppbml0X2xpc3QgPC0gY2FuZF90aG9yICU+JSAKICBtdXRhdGUobGlzdF9kYXRlID0gQ0FOX0xJU1RJTkdfRFQsIGRlYWRfZGF0ZSA9IFBFUlNfT1BUTl9ERUFUSF9EVCwgcmVtX2R0ID0gQ0FOX1JFTV9EVCkgJT4lIAogIG11dGF0ZShsaXN0X3llYXIgPSBmb3JtYXQobGlzdF9kYXRlLCAiJVkiKSkgJT4lCglmaWx0ZXIobGlzdF95ZWFyPj1zdGFydF95ZWFyICYgbGlzdF95ZWFyIDw9ZW5kX3llYXIgJiBXTF9PUkcgPT0gIkhSIikgICU+JSAKICBtdXRhdGUoc3RhdHVzID0gQ0FOX0lOSVRfU1RBVCwgCiAgICAgICAgIE9QTyA9IENBTl9MSVNUSU5HX09QT19JRCwKICAgICAgICAgZGF0ZV9zdGFydCA9IGxpc3RfZGF0ZSkKCiNyZW1vdmUgcGVkcwppZiAocGVkcyA9PSBGQUxTRSl7Cglpbml0X2xpc3QgPC0gaW5pdF9saXN0ICU+JSBmaWx0ZXIoQ0FOX0FHRV9BVF9MSVNUSU5HID4xNykJCgl0b3RfYWR1bHRzIDwtIG5yb3coaW5pdF9saXN0KQp9CgojcmVtb3ZlIG11bHRpb3JnYW4gcmVjaXBpZW50cwppZiAobXVsdGkgPT0gRkFMU0UpewoKCW11bHRpX3JlY2lwcyA8LSB0eF9ociAlPiUgZmlsdGVyKFJFQ19UWF9UWSA9PSAyIHwgUkVDX1RYX1RZID09NCkgJT4lIHNlbGVjdChQWF9JRCxSRUNfVFhfVFkpCiAgCgluX211bHRzIDwtIG5yb3coaW5pdF9saXN0ICU+JSBmaWx0ZXIoUFhfSUQgJWluJSBtdWx0aV9yZWNpcHMkUFhfSUQpKQoJCglpbml0X2xpc3QgPC0gaW5pdF9saXN0ICU+JSBmaWx0ZXIoIVBYX0lEICVpbiUgbXVsdGlfcmVjaXBzJFBYX0lEKQoKCXJlbW92ZShtdWx0aV9yZWNpcHMpCn0KCiNyZW1vdmUgY2FuZGlkYXRlcyBsaXN0ZWQgYXQgbG93IHZvbHVtZSBjZW50ZXJzCmluaXRfbGlzdCA8LSBpbml0X2xpc3QgJT4lIAogIG11dGF0ZSh0cmFuc3BsYW50ID0gaWZlbHNlKENBTl9SRU1fQ0QgPT0gNCwgMSwgMCkpICU+JQoJZ3JvdXBfYnkoQ0FOX0xJU1RJTkdfQ1RSX0lEKSAlPiUgCiAgbXV0YXRlKHRvdF90eCA9IHN1bSh0cmFuc3BsYW50LCBuYS5ybSA9IFRSVUUpKSAlPiUgdW5ncm91cCgpIAoKCm51bV9hbGxfY2VudGVycyA8LSBsZW5ndGgodW5pcXVlKGluaXRfbGlzdCRDQU5fTElTVElOR19DVFJfSUQpKQoKcmVtb3ZlZF9sb3dfdHggPC0gbnJvdyhpbml0X2xpc3QgJT4lIGZpbHRlcih0b3RfdHg8IG1pbl90eCkpCgppbml0X2xpc3QgPC0gaW5pdF9saXN0ICU+JSBmaWx0ZXIodG90X3R4Pj1taW5fdHgpIAoKI251bWJlciBvZiBsb3cgdm9sdW1lIGNlbnRlcnMKbnVtX2xvd192b2xfY2VudGVycyA8LSBudW1fYWxsX2NlbnRlcnMgLSBsZW5ndGgodW5pcXVlKGluaXRfbGlzdCRDQU5fTElTVElOR19DVFJfSUQpKQpgYGAKCgoKSWRlbnRpZnkgbGFzdCBvYnNlcnZhdGlvbiBkYXRlIGZvciBlYWNoIGNhbmRpZGF0ZQpgYGB7ciBkZWF0aF9kYXRlX2NvbnNvbGlkYXRpb24sIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiNsaW5rIHRvIHRyYW5zcGxhbnQgcmVjb3JkIGFuZCAKI2lkZW50aWZ5IGlkZW50aWZ5IGxhc3Qgb2JzZXJ2YXRpb24gZGF0ZSAoZGVhdGgsIHJlLXRyYW5zcGxhbnQsIG9yIGxhc3QgZm9sbG93LXVwKQppbml0X2xpc3QgPC0gCiAgaW5pdF9saXN0ICU+JSBsZWZ0X2pvaW4odHhfaHIgJT4lIHNlbGVjdChQWF9JRCwgVEZMX0xBU1RBVFVTLCBURkxfREVBVEhfRFQsIFRGTF9MQUZVREFURSksIAogICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gIlBYX0lEIikgJT4lIAogIG11dGF0ZSgKICAgIHRvX2RpZSA9IGNhc2Vfd2hlbigKICAgICAgQ0FOX1JFTV9DRCAlaW4lIGMoOCwgMjEpPT1UUlVFIH4gMSAsCiAgICAgIFRGTF9MQVNUQVRVUyAlaW4lIGMoIkQiLCAiUiIpID09VFJVRSB+MSwKICAgICAgaXMubmEoUEVSU19PUFROX0RFQVRIX0RUKSA9PSBGQUxTRSB+IDEsCiAgICAgIGlzLm5hKFBFUlNfU1NBX0RFQVRIX0RUKSA9PSBGQUxTRSB+IDEsCiAgICAgIFRSVUUgfjAKICApLAogIHRmbF9kYXRlID0gVEZMX0xBRlVEQVRFLAogIGRlYWRfZGF0ZSA9IGNhc2Vfd2hlbigKICAgICAgaXMubmEoUEVSU19PUFROX0RFQVRIX0RUKSA9PSBGQUxTRSB+IFBFUlNfT1BUTl9ERUFUSF9EVCwKICAgICAgVFJVRSB+IFBFUlNfU1NBX0RFQVRIX0RUKSwKICByZW1fZHQgPSBDQU5fUkVNX0RULAogIGZpbmFsX2R0ID0gY2FzZV93aGVuKAogICAgaXMubmEoZGVhZF9kYXRlKSA9PSBGQUxTRSB+IGRlYWRfZGF0ZSwKICAgIGlzLm5hKHRmbF9kYXRlKSA9PSBGQUxTRSB+IHRmbF9kYXRlLAogICAgVFJVRSB+IHJlbV9kdCkKKQoKI3ByZXZpZXcgZGF0YQppbml0X2xpc3QgJT4lIAogIHNlbGVjdChQWF9JRCwgdG9fZGllLCBsaXN0X2RhdGUsIGZpbmFsX2R0LCBDQU5fUkVNX0NELCAKICAgICAgICAgcmVtX2R0LCBSRUNfVFhfRFQsIFRGTF9MQVNUQVRVUywgdGZsX2RhdGUsIAogICAgICAgICBQRVJTX09QVE5fREVBVEhfRFQsIFBFUlNfU1NBX0RFQVRIX0RULCBkZWFkX2RhdGUpICU+JSAKICBhcnJhbmdlKGxpc3RfZGF0ZSkKYGBgCgpccGFnZWJyZWFrCgojIFNlbGVjdCBDYW5kaWRhdGUgQ292YXJpYXRlcwoKQ2FuZGlkYXRlIGNvdmFyaWF0ZXMgcmVxdWlyZWQgdG8gYXNzaWduIGluaXRpYWwgbGlzdGluZyBzdGF0dXMgdW5kZXIgdGhlIHRocmVlLXN0YXR1cyBzeXN0ZW0gYW5kIHRoZSBzaXgtc3RhdHVzIHN5c3RlbS4KQWRkaXRpb25hbCBjb3ZhcmlhdGVzIGZvciByZXZpc2lvbiBpbmNsdWRlIEFnZSwgZ2VuZGVyLCBCTUksIEJsb29kIHR5cGUsIENhcmRpYWMgRGlhZ25vc2lzLCBhbmQgc2Vuc2l0aXphdGlvbgpgYGB7ciBzZWxlY3Rfa2V5X2luaXRfdmFycywgZWNobyA9IFRSVUUgfQppbml0X2xpc3QgPC0gaW5pdF9saXN0ICU+JSAKICBzZWxlY3QoUFhfSUQsIE9QTywgQ0FOX0xJU1RJTkdfQ1RSX0lELCBzdGF0dXMsIAogICAgICAgICBkYXRlX3N0YXJ0LCBsaXN0X3llYXIsIGxpc3RfZGF0ZSwgZGVhZF9kYXRlLCBmaW5hbF9kdCwgdG9fZGllLAogICAgICAgICBDQU5fREdOLAogICAgICAgICBDQU5fUkVNX0NELCBQRVJTX09QVE5fREVBVEhfRFQsIFBFUlNfU1NBX0RFQVRIX0RULAogICAgICAgICBDQU5fSU5JVF9TVEFULAogICAgICAgICBDQU5fVkFEX1RZLCBDQU5fVkFEMSwgQ0FOX1ZBRDIsIENBTl9JVl9JTk9UUk9QLAogICAgICAgICBDQU5fSUFCUCwgQ0FOX0VDTU8sIENBTl9UQUgsCiAgICAgICAgIENBTl9DQVJESUFDX09VVFBVVCwgQ0FOX0NBUkRJQUNfT1VUUFVUX01FRFMsIAogICAgICAgICBDQU5fSEdUX0NNLCBDQU5fV0dUX0tHLAogICAgICAgICBDQU5fUENXX01FQU4sIENBTl9QQ1dfTUVBTl9NRURTLAogICAgICAgICBDQU5fQUdFX0FUX0xJU1RJTkcsIENBTl9HRU5ERVIsIENBTl9CTUksIENBTl9BQk8sIENBTl9ER04sIAogICAgICAgICBDQU5fUFJFTElNX1hNQVRDSF9SRVFVRVNUCgkpICU+JQogIG11dGF0ZShhZ2UgPSBDQU5fQUdFX0FUX0xJU1RJTkcsCiAgICAgICAgIGZlbWFsZSA9IGlmZWxzZShDQU5fR0VOREVSID09ICJGIiwgMSwgMCksCiAgICAgICAgIGJtaV9sb3cgPSBjYXNlX3doZW4oCiAgICAgICAgICAgQ0FOX0JNSSA8IHF1YW50aWxlKGluaXRfbGlzdCRDQU5fQk1JLCBwcm9icyA9IGMoMC4yNSwgMC43NSksIG5hLnJtID0gVFJVRSlbWzFdXSB+IDEsCiAgICAgICAgICAgaXMubmEoQ0FOX0JNSSkgPT0gRkFMU0UgfiAwCiAgICAgICAgICksCiAgICAgICAgIGJtaV9oaWdoID0gY2FzZV93aGVuKAogICAgICAgICAgIENBTl9CTUkgPiBxdWFudGlsZShpbml0X2xpc3QkQ0FOX0JNSSwgcHJvYnMgPSBjKDAuMjUsIDAuNzUpLCBuYS5ybSA9IFRSVUUpW1syXV0gfiAxLAogICAgICAgICAgIGlzLm5hKENBTl9CTUkpID09IEZBTFNFIH4gMAogICAgICAgICApLAogICAgICAgICBibG9vZF90eXBlID0gZmFjdG9yKAogICAgICAgICAgIGNhc2Vfd2hlbigKICAgICAgICAgICAgIENBTl9BQk8gJWluJSBjKCJBIiwgIkExIiwgIkEyIikgfiAiQSIsCiAgICAgICAgICAgICBDQU5fQUJPICVpbiUgYygiQTFCIiwgIkEyQiIpIH4gIkFCIiwKICAgICAgICAgICAgIFRSVUUgfiBDQU5fQUJPKQogICAgICAgICAgICksCiAgICAgICAgc2ltcGxlX2RpYWcgPSBjYXNlX3doZW4oCiAgICAgICAgICBDQU5fREdOPjk5OSAmIENBTl9ER048MTAwNyB+ICJEaWxhdGVkIGNhcmRpb215b3BhdGh5LCBub24taXNjaGVtaWMiLAogICAgICAgICAgQ0FOX0RHTiA9PSAxMDA3IHwgQ0FOX0RHTiA9PTEyMDAgfiAiSXNjaGVtaWMgY2FyZGlvbXlvcGF0aHkiLAogICAgICAgICAgQ0FOX0RHTj4xMDQ4ICYgQ0FOX0RHTjwgMTEwMCB+ICJSZXN0cmljdGl2ZSBjYXJkaW9teW9wYXRoeSIsCiAgICAgICAgICBUUlVFIH4gIk90aGVyIgogICAgICAgICksCiAgICAgICAgc2ltcGxlX2RpYWcgPSBmYWN0b3Ioc2ltcGxlX2RpYWcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJEaWxhdGVkIGNhcmRpb215b3BhdGh5LCBub24taXNjaGVtaWMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSXNjaGVtaWMgY2FyZGlvbXlvcGF0aHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVzdHJpY3RpdmUgY2FyZGlvbXlvcGF0aHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT3RoZXIiKSksCiAgICAgICAgY3Jvc3NfbWF0Y2ggPSBpZmVsc2UoQ0FOX1BSRUxJTV9YTUFUQ0hfUkVRVUVTVCA9PSAiWSIsIDEsIDApCiAgKQoKdGFibGUoaW5pdF9saXN0JGJsb29kX3R5cGUpCnJlbW92ZShjYW5kX3Rob3IpCmBgYAoKCiNTZWxlY3QgVHJhbnNwbGFudCBSZWNpcGllbnQgYW5kIERvbm9yIENvdmFyaWF0ZXMKS2VlcCB0cmFuc3BsYW50IGFuZCBEb25vciB2YXJpYWJsZXMgdXNlZCBpbiBkb25vciByaXNrIGluZGV4IHNjb3JlCiogRG9ub3IgQWdlCiogRG9ub3IgQlVOL0NyCiogSXNjaGVtaWMgdGltZQoqIFJhY2UgTWlzbWF0Y2gKCkFuZCBvdGhlciByZWNpcGllbnQgY292YXJpYXRlcyB0byBnZW5lcmF0ZSB0YWJsZSBTNCBpbiB0aGUgc3VwcGxlbWVudCAoY29tcGFyaXNvbiBvZiByZWNpcGllbnQgY2hhcmFjdGVyaXN0aWNzIGF0IGhpZ2ggYW5kIGxvdyBiZW5lZml0IGNlbnRlcnMpCgoxLiBSZW5hbCBmdW5jdGlvbgoyLiBDYXJkaWFjIGRpYWdub3NpcwozLiBIaXN0b3J5IG9mIENhcmRpYWMgU3VyZ2VyeQo0LiBBZ2UKNS4gTGlzdGluZyBTdGF0dXMKNi4gU3VwcG9ydCAoTUNTKQo3LiBJQ0QKOC4gQk1JCjkuIEZ1bmN0aW9uYWwgU3RhdHVzCjEwLiBHZW5kZXIKMTEuIFJhY2UKMTUuIEhlbW9keW5hbWljcyAoQ2FyZGlhYyBpbmRleCBhbmQgUHVsbW9uYXJ5IFdlZGdlIHByZXNzdXJlKQoKCmBgYHtyIHNlbGVjdF90eF9kb25vciB9CnR4IDwtIHR4X2hyICU+JSBmaWx0ZXIoUFhfSUQgJWluJSBpbml0X2xpc3QkUFhfSUQpICU+JQoJbXV0YXRlKHR4X2RhdGU9IFJFQ19UWF9EVCwKCSAgICAgICB0ZmxfZGF0ZSA9IFRGTF9MQUZVREFURSwKCSAgICAgICBzdGF0dXMgPSBDQU5fTEFTVF9TVEFUKSAlPiUgCglhcnJhbmdlKFBYX0lELCB0eF9kYXRlKQoKdHggPC0gdHggJT4lIHNlbGVjdChQWF9JRCwgUkVDX09QT19JRCwgUkVDX0NUUl9JRCwgRE9OT1JfSUQsIHN0YXR1cywgdHhfZGF0ZSwgQ0FOX1JBQ0UsCglDQU5fRElBQl9UWSwgQ0FOX0RJQUIsCglSRUNfQ1JFQVQsIFJFQ19ESUFMLAoJUkVDX0RHTiwgCglSRUNfQ0FSRElBQ19TVVJHLCAKCVJFQ19WQURfVFksIFJFQ19WQUQxLCBSRUNfVkFEMiwgUkVDX0lOT1RST1AsIAoJUkVDX0lBQlAsIFJFQ19FQ01PLCAKCVJFQ19JTVBMQU5UX0RFRklCLCAKCVJFQ19CTUksCglSRUNfRlVOQ1ROX1NUQVQsIAoJUkVDX0NBUkRJQUNfT1VUUFVULCBSRUNfQ0FSRElBQ19PVVRQVVRfTUVEUywgUkVDX0hHVF9DTSwgUkVDX1dHVF9LRywKCVJFQ19QQ1dfTUVBTiwgUkVDX1BDV19NRUFOX01FRFMsCglSRUNfUFVMTV9BUlRfTUVBTiwgUkVDX1BVTE1fQVJUX01FQU5fTUVEUywKCVJFQ19IUl9JU0NILAoJVEZMX0xBU1RBVFVTLCBURkxfTEFGVURBVEUKKQoKCmRvbm9zIDwtIGRvbm9yX2RlY2Vhc2VkICU+JSBmaWx0ZXIoRE9OT1JfSUQgJWluJSB0eCRET05PUl9JRCkgJT4lIAogIG11dGF0ZShET05fQlVOID0gYXMuaW50ZWdlcihET05fQlVOKSwgCiAgICAgICAgIERPTl9DUkVBVCA9IGFzLmludGVnZXIoRE9OX0NSRUFUKSkKCmRvbm9zIDwtIGRvbm9zICU+JSBzZWxlY3QoRE9OT1JfSUQsIERPTl9PUE9fQ1RSX0lELAogIERPTl9BR0UsCglET05fUkFDRSwKCURPTl9DUkVBVCwgRE9OX0JVTgoJKQoKdHggPC0gbGVmdF9qb2luKHR4LCBkb25vcywgYnkgPSAiRE9OT1JfSUQiKQoKdHggPC0gdHggJT4lIG11dGF0ZSgKCXdoaXRlX3JlY2lwID0gaWZlbHNlKENBTl9SQUNFID09IDgsMSwwKSwKCXdoaXRlX2Rvbm9yID0gaWZlbHNlKERPTl9SQUNFID09IDgsMSwwKSwKCXNpbXBsZV9yYWNlID0gY2FzZV93aGVuKAoJCUNBTl9SQUNFID09IDggfiAiV2hpdGUiLCAKCQlDQU5fUkFDRSA9PSAxNiB+ICJCbGFjayIsIAoJCUNBTl9SQUNFID09IDIwMDAgfiAiSGlzcGFuaWMiLCAKCQlDQU5fUkFDRSA9PSA2NCB+ICJBc2lhbiIsIAoJCVRSVUUgfiAiT3RoZXIiKSwKCXNpbXBsZV9kb25fcmFjZSA9IGNhc2Vfd2hlbigKCQlET05fUkFDRSA9PSA4IH4gIldoaXRlIiwgCgkJRE9OX1JBQ0UgPT0gMTYgfiAiQmxhY2siLCAKCQlET05fUkFDRSA9PSAyMDAwIH4gIkhpc3BhbmljIiwgCgkJRE9OX1JBQ0UgPT0gNjQgfiAiQXNpYW4iLCAKCQlUUlVFIH4gIk90aGVyIiksCglibGFjayA9IGlmZWxzZShzaW1wbGVfcmFjZSA9PSAiQmxhY2siLCAxLCAwKSwKCWJsYWNrX2RvbiA9IGlmZWxzZShzaW1wbGVfZG9uX3JhY2UgPT0gIkJsYWNrIiwgMSwgMCksCglkcnMgPSBjYXNlX3doZW4oCgkJCVJFQ19IUl9JU0NILzYwIDwgMiB+IDEsCgkJCVJFQ19IUl9JU0NILzYwID49IDIgJiBSRUNfSFJfSVNDSC82MCA8IDQgfiAyLAoJCQlSRUNfSFJfSVNDSC82MCA+PTQgJiBSRUNfSFJfSVNDSC82MCA8IDYgfiAzLAoJCQlSRUNfSFJfSVNDSC82MCA+PSA2ICYgUkVDX0hSX0lTQ0gvNjAgPCA4IH40LAoJCQlUUlVFIH4gNQoJCSkrCgkJY2FzZV93aGVuKAoJCQlET05fQUdFID49NDAgJiBET05fQUdFIDw1MCB+IDMsCgkJCURPTl9BR0UgPj0gNTAgfiA1LAoJCQlUUlVFIH4gMAoJCSkgKwoJCWNhc2Vfd2hlbigKCQkJKERPTl9CVU4vRE9OX0NSRUFUKSA+IDMwIH4gMywKCQkJVFJVRSB+IDAKCQkpICsKCQljYXNlX3doZW4oCgkJCWJsYWNrICE9IGJsYWNrX2RvbiB+IDIsCgkJCVRSVUUgfiAwCgkJKQoJKQoKI2lkZW50aWZ5ICJvdmVydHJlYXRlZCIgcmVjaXBpZW50cyBiYXNlZCBvbiByZWNpcGllbnQgaGVtb2R5bmFtaWNzLiAKdHggPC0gdHggJT4lIG11dGF0ZSgKCWJzYSA9IDAuMDA3MTg0KihSRUNfSEdUX0NNKV4oMC43MjUpKlJFQ19XR1RfS0deKDAuNDI1KSwKCXJlY2lwX3Bjd3AgPSBhcy5udW1lcmljKFJFQ19QQ1dfTUVBTiksCglyZWNpcF9jaSA9IFJFQ19DQVJESUFDX09VVFBVVC9ic2EsCiAJaWFicF9yZWNfbm9fc2hvY2sgPSBjYXNlX3doZW4oCiAJCXJlY2lwX3Bjd3AgPCAxNSAmIFJFQ19JQUJQID09MSB+IDEsCiAgICAJcmVjaXBfY2kgPiAxLjggJiBSRUNfQ0FSRElBQ19PVVRQVVRfTUVEUyA9PSAiTiIgJiBSRUNfSUFCUCA9PTEgfiAxLAogICAgCXJlY2lwX2NpID4gMi4wICYgUkVDX0lBQlAgPT0xIH4gMQogIAkJKSwKCXJlY2lwX292ZXJ0cmVhdCA9IGNhc2Vfd2hlbigKCQlyZWNpcF9wY3dwIDwgMTUgJiBSRUNfSU5PVFJPUCA9PTEgJiBSRUNfVkFEX1RZID09IDEgfiAxLAogICAgCXJlY2lwX2NpID4gMS44ICYgUkVDX0NBUkRJQUNfT1VUUFVUX01FRFMgPT0gIk4iICYgUkVDX0lOT1RST1AgPT0xICYgUkVDX1ZBRF9UWSA9PSAxIH4gMSwKICAgIAlyZWNpcF9jaSA+IDIuMiAmIFJFQ19JTk9UUk9QID09MSAmIFJFQ19WQURfVFkgPT0gMX4gMSwKCQlyZWNpcF9wY3dwIDwgMTUgJiBSRUNfSUFCUCA9PTEgJiBSRUNfVkFEX1RZID09IDEgfiAxLAogICAgCXJlY2lwX2NpID4gMS44ICYgUkVDX0NBUkRJQUNfT1VUUFVUX01FRFMgPT0gIk4iICYgUkVDX0lBQlAgPT0xICYgUkVDX1ZBRF9UWSA9PSAxfiAxLAogICAgCXJlY2lwX2NpID4gMi4wICYgUkVDX0lBQlAgPT0xICYgUkVDX1ZBRF9UWSA9PSAxfiAxCgkpCikKCgojcmVtb3ZlIHRoZSByYWNlIHZhcmlhYmxlIHRvIGF2b2lkIHJlZHVuZGFuY3kKdHggPC0gdHggJT4lIHNlbGVjdCgtQ0FOX1JBQ0UpCgoKcmVtb3ZlKHR4X2hyLCBkb25vcl9kZWNlYXNlZCwgZG9ub3MpCgojcHJldmlldyB0cmFuc3BsYW50IHJlY2lwaWVudCBkYXRhc2V0CnR4CmBgYAoKClxwYWdlYnJlYWsKCiMgTWVyZ2UgZGF0YSBzZXRzIHRvIGNyZWF0ZSB0aW1lIHNlcmllcwpGaWx0ZXIgc3RhdHVzIGhpc3RvcnkgZmlsZSBhbmQgc2VsZWN0IGtleSB2YXJpYWJsZXMKCiogU3RhdHVzIDFBID0gMjAxMAoqIFN0YXR1cyAxQiA9IDIwMjAKKiBTdGF0dXMgMiA9IDIwMzAKKiBJbmFjdGl2ZSA9IDI5OTkKYGBge3Igc2VsZWN0X2hpc3RvcnlzLCBlY2hvID0gVFJVRSB9Cmhpc3QgPC0gc3RhdGhpc3RfdGhvciAlPiUgZmlsdGVyKFBYX0lEICVpbiUgaW5pdF9saXN0JFBYX0lEKSAlPiUgCgltdXRhdGUoZGF0ZV9zdGFydCA9IENBTkhYX0JFR0lOX0RULCAKCSAgICAgICBkYXRlX2VuZCA9IENBTkhYX0VORF9EVCwgCgkgICAgICAgc3RhdHVzID0gQ0FOSFhfU1RBVF9DRCwgCgkgICAgICAgcmVhbF9zdGF0dXMgPSBDQU5IWF9TVEFUX0NELCAKCSAgICAgICByZW1fZHQgPSBDQU5fUkVNX0RUKSAlPiUgCglhcnJhbmdlKFBYX0lELCBkYXRlX3N0YXJ0KSAlPiUgCiAgc2VsZWN0KFBYX0lELCBzdGF0dXMsIHJlYWxfc3RhdHVzLCBkYXRlX3N0YXJ0LCBkYXRlX2VuZCwgcmVtX2R0LCAgQ0FOX1JFTV9DRCkKCmhpc3QgPC0gZGlzdGluY3QoaGlzdCwgUFhfSUQsIGRhdGVfc3RhcnQsIC5rZWVwX2FsbCA9IFRSVUUpCgpyZW1vdmUoc3RhdGhpc3RfdGhvcikKCiNwcmV2aWV3IHN0YXR1cyBoaXN0b3J5IGRhdGEgc2V0Cmhpc3QKYGBgCgpGaWx0ZXIgc3RhdHVzIDFBIGp1c3RpZmljYXRpb24gZmlsZSBhbmQgc2VsZWN0IGtleSB2YXJpYWJsZXMKYGBge3Igc2VsZWN0X2p1c3RfMWF9Cmp1c3RfMWEgPC0gc3RhdGp1c3RfaHIxYSAlPiUgCiAgZmlsdGVyKFBYX0lEICVpbiUgaW5pdF9saXN0JFBYX0lEKSAgJT4lIAoJbXV0YXRlKGRhdGVfc3RhcnQgPSBDQU5IWF9DSEdfRFQsIAoJCXN0YXR1cyA9IENBTkhYX1NUQVRfQ0QpICU+JSAKCWFycmFuZ2UoUFhfSUQsIGRhdGVfc3RhcnQpIAoKI3JlbW92ZSByZWR1bmRhbnQgb3IgZXJyb25lb3VzIGp1c3RpZmljYXRpb25zCmp1c3RfMWEgPC0gZGlzdGluY3QoanVzdF8xYSkgJT4lIAogIGZpbHRlcihDQU5IWF9GT1JNX1NUQVQgPT0gNCB8IENBTkhYX0ZPUk1fU1RBVCA9PSA4KSAlPiUgCiAgZGlzdGluY3QoUFhfSUQsIGRhdGVfc3RhcnQsIC5rZWVwX2FsbCA9IFRSVUUpCgoKI3NlbGVjdCBrZXkgdmFyaWFibGVzCmp1c3RfMWEgPC0ganVzdF8xYSAlPiUgc2VsZWN0KFBYX0lELCBDQU5fTElTVElOR19DVFJfSUQsIAogIHN0YXR1cywgZGF0ZV9zdGFydCwgQ0FOSFhfU1RBVF9UWSwgQ0FOSFhfRk9STV9TVEFULCAKCUNBTkhYX0RJQUxZU0lTLCBDQU5IWF9MQUJfU0VSVU1fQ1JFQVQsIAoJQ0FOSFhfQURVTFRfQ1JJVEVSSUFfQSwgQ0FOSFhfQURVTFRfQ1JJVEVSSUFfQiwgCiAgQ0FOSFhfQURVTFRfQ1JJVEVSSUFfQywgQ0FOSFhfQURVTFRfQ1JJVEVSSUFfRCwgCiAgQ0FOSFhfQURVTFRfQ1JJVEVSSUFfRSwgQ0FOSFhfSU5UUlBfRE9CVSwgQ0FOSFhfSU5UUlBfRE9QQSwgQ0FOSFhfSU5UUlBfTUlMUklOLAoJQ0FOSFhfQURNSVRURUQsIAoJQ0FOSFhfSUFCUCwgQ0FOSFhfRUNNTywgQ0FOSFhfTFZBRF9UWVBFLCBDQU5IWF9WQUQsIENBTkhYX1RBSCwgQ0FOSFhfUlZBRF9UWVBFLAoJQ0FOSFhfTEFCX0JJTEksIAoJQ0FOSFhfQ0FSRF9PVVRQVVQsIENBTkhYX0hFTU9fQ0ksIENBTkhYX0hFTU9fSU5UUlBfT0JUQUlORUQsIENBTkhYX0hFTU9fQlNBLAoJQ0FOSFhfSEVNT19QQ1dQLAoJQ0FOSFhfSEVNT19NUEFQLAoJQ0FOSFhfREVWX01BTEZVTkNUTiwKCUNBTkhYX0RFVl9WRU5UX0FSUllUSE0KCSkKCnJlbW92ZShzdGF0anVzdF9ocjFhKQoKanVzdF8xYQpgYGAKCgpGaWx0ZXIgc3RhdHVzIDFCIGp1c3RpZmNhdGlvbiBmaWxlIGFuZCBzZWxlY3Qga2V5IHZhcmlhYmxlcy4gVGhlc2UgZm9ybXMgaGF2ZSBhIGxvdCBsZXNzIGluZm9ybWF0aW9uLCBtYWlubHkganVzdCByZXBvcnQgVkFEIHZzLiBpbm90cm9wZXMKYGBge3Igc2VsZWN0XzFifQpqdXN0XzFiIDwtIHN0YXRqdXN0X2hyMWIgJT4lIGZpbHRlcihQWF9JRCAlaW4lIGluaXRfbGlzdCRQWF9JRCkgJT4lIAoJbXV0YXRlKGRhdGVfc3RhcnQgPSBDQU5IWF9DSEdfRFQsIAoJCXN0YXR1cyA9IENBTkhYX1NUQVRfQ0QsIAoJCXN0YWJsZV9sdmFkID0gQ0FOSFhfVkFELCAKCQlleGNlcHRfMWIgPUNBTkhYX0NSSVRfTk9UX01FVCwKCQlsb3dfZG9zZV9pbm8gPSBwbWF4KENBTkhYX1JFUVVJUkVfTE9XX0lOT1RST1AsIENBTkhYX0NPTlRfSVZfSU5PVFJPUCkKCQkpICU+JSAKCWFycmFuZ2UoUFhfSUQsIGRhdGVfc3RhcnQpCgoKanVzdF8xYiA8LSBkaXN0aW5jdChqdXN0XzFiKSAlPiUgCiAgZmlsdGVyKENBTkhYX0ZPUk1fU1RBVCA9PSA0IHwgQ0FOSFhfRk9STV9TVEFUID09IDgpICU+JQkKICBkaXN0aW5jdChQWF9JRCwgZGF0ZV9zdGFydCwgLmtlZXBfYWxsID0gVFJVRSkKCmp1c3RfMWIgPC0ganVzdF8xYiAlPiUgCiAgc2VsZWN0KFBYX0lELCBDQU5fTElTVElOR19DVFJfSUQsIHN0YXR1cywgZGF0ZV9zdGFydCwgCglsb3dfZG9zZV9pbm8sIHN0YWJsZV9sdmFkLCBleGNlcHRfMWIKCSkKCnJlbW92ZShzdGF0anVzdF9ocjFiKSAKCmp1c3RfMWIKYGBgCgoKTWVyZ2UgZGF0YSBzZXRzIHRvIGNyZWF0ZSB0aW1lIHNlcmllcwpgYGB7ciBjcmVhdGVfY2FuZF90aW1lX3NlcmllcywgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UgfQojbWVyZ2Ugd2l0aCBoaXN0b3J5IApjYW5kX3RpbWVfc2VyaWVzIDwtIGluaXRfbGlzdCAlPiUgCiAgbXV0YXRlKGludF9mb3JtID0xLCByZW1fY2QgPSBDQU5fUkVNX0NEKSAlPiUgCiAgZnVsbF9qb2luKGhpc3QsIGMoIlBYX0lEIiwgImRhdGVfc3RhcnQiLCAic3RhdHVzIiksIHN1ZmZpeCA9IGMoIi5pbml0IiwgIi5oaXN0IikpICU+JSAKICBhcnJhbmdlKFBYX0lELCBkYXRlX3N0YXJ0KQoKCiNtZXJnZSB3aXRoIDFBIGp1c3RpZmljYXRpb25zLCBrZWVwaW5nIGp1c3RpZmljYXRpb24gZm9ybXMgaW4gdGhlIG1pZGRsZSBvZiBhIGhpc3RvcnkgcGVyaW9kCmNhbmRfdGltZV9zZXJpZXMgPC0gY2FuZF90aW1lX3NlcmllcyAlPiUgCiAgZnVsbF9qb2luKGp1c3RfMWEsIGJ5ID0gYygiUFhfSUQiLCAiZGF0ZV9zdGFydCIsICJzdGF0dXMiKSwgc3VmZml4ID0gYygiLmluaXQiLCAiLmoxYSIpKSAgJT4lIAogIGFycmFuZ2UoUFhfSUQsIGRhdGVfc3RhcnQpCgojbWVyZ2Ugd2l0aCAxQiBqdXN0aWNpYXRpb25zLCBrZWVwaW5nIGp1c3RpZmljYXRpb24gZm9ybXMgaW4gdGhlIG1pZGRsZSBvZiBhIGhpc3RvcnkgcGVyaW9kCmNhbmRfdGltZV9zZXJpZXMgPC0gY2FuZF90aW1lX3NlcmllcyAlPiUgCiAgZnVsbF9qb2luKGp1c3RfMWIsIGJ5ID0gYygiUFhfSUQiLCAiZGF0ZV9zdGFydCIsICJzdGF0dXMiKSwgc3VmZml4ID0gYygiLmluaXQiLCAiLmoxYiIpKSAlPiUgCiAgYXJyYW5nZShQWF9JRCwgZGF0ZV9zdGFydCkgCgojY2Fycnlmb3J3YXJkICJyZWFsIHN0YXR1cyIgc3RhdHVzIGhpc3RvcnkgZGF0YXNldApjYW5kX3RpbWVfc2VyaWVzIDwtIGNhbmRfdGltZV9zZXJpZXMgJT4lIGFycmFuZ2UoUFhfSUQsIGRhdGVfc3RhcnQpICU+JSAKICBncm91cF9ieShQWF9JRCkgJT4lIAogIG11dGF0ZShyZWFsX3N0YXR1cyA9IG5hLmxvY2YocmVhbF9zdGF0dXMsIG5hLnJtID0gRkFMU0UpKSAlPiUgCiAgdW5ncm91cCgpIAoKI3JlbW92ZSBqdXN0aWZpY2F0aW9uIGZvcm1zIHRoYXQgZGlkbid0IGFjdHVhbGx5IGNoYW5nZSBvZmZpY2FsIHN0YXR1cwpjYW5kX3RpbWVfc2VyaWVzIDwtIGNhbmRfdGltZV9zZXJpZXMgJT4lIAogIGZpbHRlcihyZWFsX3N0YXR1cyA9PSBzdGF0dXMgfCBpbnRfZm9ybSA9PTEpCgoKCmBgYAoKCkFkZCB0cmFuc3BsYW50IGZpbGVzIHRvIHRpbWUgc2VyaWVzCmBgYHtyIGFkZF90eCwgIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQoKY2FuZF90aW1lX3NlcmllcyA8LSBjYW5kX3RpbWVfc2VyaWVzICU+JSAKICBtdXRhdGUoZGF0ZSA9IGRhdGVfc3RhcnQpCgp0eCA8LSB0eCAlPiUgbXV0YXRlKGRhdGUgPSB0eF9kYXRlKQoKdGltZV9zZXJpZXMgPC0gY2FuZF90aW1lX3NlcmllcyAlPiUgCiAgZnVsbF9qb2luKHR4LCBieSA9IGMoIlBYX0lEIiwgImRhdGUiLCAic3RhdHVzIiksIHN1ZmZpeCA9IGMoIi5jYW5kIiwgIi50eCIpKSAlPiUgCiAgYXJyYW5nZShQWF9JRCwgZGF0ZSkgCgoKI3ZlcmlmeSBpbml0aWFsIHN0YXR1cyBjb3VudHMgYXJlIHRoZSBzYW1lIChub3QgcnVuKQojIGluaXRfbGlzdCAlPiUgY291bnQoc3RhdHVzKQojIGNhbmRfdGltZV9zZXJpZXMgJT4lIGZpbHRlcihpbnRfZm9ybT09MSkgJT4lIGNvdW50KHN0YXR1cykKI3RpbWVfc2VyaWVzICU+JSBmaWx0ZXIoaW50X2Zvcm09PTEpICU+JSBjb3VudCgpCmBgYApUaGVyZSBhcmUgYSB0b3RhbCBvZiBgciBucm93KHRpbWVfc2VyaWVzKWAgb2JzZXJ2YXRpb25zIGluIHRoZSBkYXRhc2V0IGZvciBgciBsZW5ndGgodW5pcXVlKHRpbWVfc2VyaWVzJFBYX0lEKSlgIGNhbmRpZGF0ZXMgbGlzdGVkIGR1cmluZyB0aGUgc3R1ZHkgcGVyaW9kLiBUaGUgcG9zdC10cmFuc3BsYW50IHBlcmlvZCBpcyBjb25zaWRlcmVkIG9uZSBvYnNlcnZhdGlvbi4KCkNvbnZlcnQgZGF0ZXMgdG8gc3RhcnQvc3RvcCB0aW1lIGluIGRheXMgdmFyaWFibGVzCmBgYHtyIGxhc3Rfb2IsIGVjaG8gPSBUUlVFIH0KCiNjYXJyeWZvcndhcmQga2V5IGRhdGVzIGFuZCBkZWF0aCBzdGF0dXMKdHMgPC0gdGltZV9zZXJpZXMgJT4lIHVuZ3JvdXAoKSAlPiUgCiAgYXJyYW5nZShQWF9JRCwgZGF0ZSkgJT4lIAogIGdyb3VwX2J5KFBYX0lEKSAlPiUgCiAgbXV0YXRlKAogICAgdHggPSBpZl9lbHNlKGlzLm5hKHR4X2RhdGUpPT1GQUxTRSwgMSwgMCksIAogIAl0b19kaWUgPSBuYS5sb2NmKHRvX2RpZSwgbmEucm0gPSBGQUxTRSksCiAgICBmaW5hbF9kdCA9IG5hLmxvY2YoZmluYWxfZHQsIG5hLnJtID0gRkFMU0UpLAogICAgbGlzdF9kYXRlID0gbmEubG9jZihsaXN0X2RhdGUsIG5hLnJtID0gRkFMU0UpCikKCgojY3JlYXRlIHRpbWUgKGRheXMpIHZhcmlhYmxlCnRzIDwtIHRzICU+JSBncm91cF9ieShQWF9JRCkgJT4lIG11dGF0ZSgKICB0XzEgPSBhcy5udW1lcmljKGRhdGUtbGlzdF9kYXRlKSwKCWxhc3Rfb2IgPSBpZl9lbHNlKHJvd19udW1iZXIoKT09bigpLCAxLCAwKSwKICB0XzIgPSBpZmVsc2UobGFzdF9vYiA9PTAsIGxlYWQodF8xKSwgZmluYWxfZHQgLSBsaXN0X2RhdGUpCikgJT4lIHVuZ3JvdXAoKQoKCiMgY2FwdHVyZSB0cmFuc3BsYW50IHByb2NlZHVyZSBkZWF0aHMKIyBUaGlzIGNhcHR1cmVzIGh5cGVyYWN1dGUgcGVyaW9wZXJhdGl2ZSByaXNrLiBBbHNvIGNhcHR1cmUgb25lIGRheSBsaXN0aW5ncyBvZiBhbnkgdHlwZQp0cyA8LSB0cyAlPiUgCiAgbXV0YXRlKCB0XzIgPSBpZmVsc2UodF8xID09IHRfMiAmIHR4ID09MSAmIGRhdGUgPT0gZmluYWxfZHQgJiB0b19kaWUgPT0xLCB0XzIgKyAxLCB0XzIpLAogICAgICAgICAgdF8yID0gaWZlbHNlKHRfMSA9PSB0XzIgJiBsaXN0X2RhdGUgPT0gZmluYWxfZHQgJiBpbnRfZm9ybSA9PTEsIHRfMiArIDEsIHRfMikpCgojZmlsdGVyIG91dCBvbmUgZGF5IHBlcmlvZHMgYW5kIGVycm9uZW91cyBkYXRpbmdzIAojKHdoZXJlIGxpc3RpbmcgZGF0ZSBpcyBhZnRlciB0aGUgZGVhdGggZGF0ZSBpbiBzb2NpYWwgc2VjdXJpdHkgZGVhdGggbWFzdGVyIGZpbGUpLiAKI1RoaXMgZXJyb25lb3VzIGxpc3RpbmdzIGFyZSBpbmNsdWRpbmcgYXMgaW4gdGhlIGV4Y2x1c2lvbnMgaW4gRmlndXJlIDEpCnRzIDwtIHRzICU+JQogIGZpbHRlcih0XzIgPiB0XzEpICU+JSAKICBncm91cF9ieShQWF9JRCkgJT4lCiAgbXV0YXRlKAogICAgbGFzdF9vYiA9IGlmX2Vsc2Uocm93X251bWJlcigpPT1uKCksIDEsIDApLAogICAgZGVhZCA9IGlmX2Vsc2UobGFzdF9vYiA9PTEgJiB0b19kaWUgPT0xLCAxLCAwKQogICkgJT4lIAogIHVuZ3JvdXAoKQoKI3ByZXZpZXcgY2xlYW4gdGltZSBzZXJpZXMgZGF0YQp0cyAlPiUgc2VsZWN0KFBYX0lELCBzdGF0dXMsdHgsIHRfMSwgdF8yLCBkZWFkLCBkYXRlLCBsaXN0X2RhdGUsIGZpbmFsX2R0KQoKIzEzNyBkYXRlIGVudHJ5IGVycm9ycyBiZWxvdwojdHMgJT4lIGZpbHRlcihpbnRfZm9ybT09MSkgJT4lIGNvdW50KCkKYGBgCgoKYGBge3IgY2VudGVyX09QT30KI2NyZWF0ZSBjZW50ZXIgYW5kIE9QTyB2YXJpYWJsZXMKdHMgPC0gdHMgJT4lIG11dGF0ZSgKICBjZW50ZXIgPSBjYXNlX3doZW4oCiAgCWlzLm5hKENBTl9MSVNUSU5HX0NUUl9JRC5pbml0KSA9PSBGQUxTRSB+IENBTl9MSVNUSU5HX0NUUl9JRC5pbml0LAogIAlpcy5uYShDQU5fTElTVElOR19DVFJfSUQuajFhKSA9PSBGQUxTRSB+IENBTl9MSVNUSU5HX0NUUl9JRC5qMWEsCiAgCWlzLm5hKFJFQ19DVFJfSUQpID09IEZBTFNFIH4gUkVDX0NUUl9JRAoJKSwgCiAgY2VudGVyID0gbmEubG9jZihjZW50ZXIpKQoKdHMgPC0gdHMgJT4lIG11dGF0ZSgKICBPUE8gPSBjYXNlX3doZW4oCglpcy5uYShSRUNfT1BPX0lEKSA9PSBGQUxTRSB+IFJFQ19PUE9fSUQsCglUUlVFIH4gT1BPCgkpLCAgT1BPID0gbmEubG9jZihPUE8pKQoKCnRzICU+JSBzZWxlY3QoUFhfSUQsIGNlbnRlciwgT1BPLCBzdGF0dXMsIHRfMSwgdF8yLCB0eCwgZGVhZCkKYGBgCgpccGFnZWJyZWFrCgojIENvZGUgc2l4LXN0YXR1cyBkZXNpZ25hdGlvbnMKCkdlbmVyYXRlIAoqIGBzdGF0X2p1c3RgLCBhIHZhcmlhYmxlIHRvIHRoYXQgaWRlbnRpZmllcyB0aHJlZS1zdGF0dXMganVzdGlmaWNhdGlvbnMgYW5kIGluYWN0aXZlIHN0YXR1c2VzCiogYHRocmVlX3N0YXR1c2AsIGEgdmFyaWFibGUgdGhhdCBpcyBtaXNzaW5nIHdoZW4gaW5hY3RpdmUgYW5kIGp1c3QgcmVjb3JkcyBhY3RpdmUgdGhyZWUtc3RhdHVzCiogYGVyYV90eGAgKHRyYW5zcGxhbnQgeWVhciBkaWNob3RvbWl6ZWQpCiogYHR4X3Jpc2t5X2RvbmAgKGRvbm9yIHJpc2sgc2NvcmUgPiA1KSB0cmFuc3BsYW50IG1vZGlmeWluZyB2YXJpYWJsZXMKYGBge3IgZGVmaW5lX2tleV92YXJzfQpmaW5hbCA8LSB0cyAlPiUgCiAgbXV0YXRlKAogIHN0YXRfanVzdCA9IGNhc2Vfd2hlbigKICAgIENBTkhYX0FEVUxUX0NSSVRFUklBX0EgPT0xfiAiU3RhdHVzIDFBIChNQ1MgZm9yIHNob2NrKSIsCiAgICBDQU5IWF9BRFVMVF9DUklURVJJQV9CID09IDEgfiAiU3RhdHVzIDFBIChNQ1MgY29tcGxpY2F0aW9uKSIsCiAgICBDQU5IWF9BRFVMVF9DUklURVJJQV9DID09IDEgfiAiU3RhdHVzIDFBIChNZWNoYW5pY2FsIHZlbnRpbGF0aW9uKSIsCiAgICBDQU5IWF9BRFVMVF9DUklURVJJQV9EID09IDEgfiAiU3RhdHVzIDFBIChIaWdoIGRvc2UgaW5vdHJvcGVzKSIsCiAgICBDQU5IWF9BRFVMVF9DUklURVJJQV9FID09IDEgfiAiU3RhdHVzIDFBIChFeGNlcHRpb24pIiwKICAgIHN0YXR1cyA9PSAyMDEwICYgdHggPT0gMCB+ICJTdGF0dXMgMUEgKG5vIGp1c3RpZmljYXRpb24gbGlzdGVkKSIsCiAgICBzdGF0dXMgPT0gMjAxMCAmIHR4ID09IDEgJiB0XzEgPT0gMCB+ICJTdGF0dXMgMUEgKG5vIGp1c3RpZmljYXRpb24gbGlzdGVkKSIsCiAgICBzdGF0dXMgPT0gMjAyMCAmIGxvd19kb3NlX2lubyA9PTEgIH4gIlN0YXR1cyAxQiAoaW5vdHJvcGVzKSIsCiAgICBzdGF0dXMgPT0gMjAyMCAmIHN0YWJsZV9sdmFkID09MSB+ICJTdGF0dXMgMUIgKHN0YWJsZSBWQUQpIiwKICAgIHN0YXR1cyA9PSAyMDIwICYgZXhjZXB0XzFiID09MSB+ICJTdGF0dXMgMUIgKEV4Y2VwdGlvbikiLAogICAgc3RhdHVzID09IDIwMjAgJiB0eCA9PSAwIH4gIlN0YXR1cyAxQiAoTm8ganVzdGlmaWNhdGlvbiBsaXN0ZWQpIiwKICAgIHN0YXR1cyA9PSAyMDMwICB+ICJTdGF0dXMgMiIsCiAgICBzdGF0dXMgPT0gMjk5OSB+ICJJbmFjdGl2ZSIpLAogIHR4X3llYXIgPSBhcy5udW1lcmljKGZvcm1hdCh0eF9kYXRlLCAiJVkiKSksCiAgZXJhX3R4ID0gaWZlbHNlKCh0eF95ZWFyPD0yMDEwKSAmIHR4ID09MSwgMSwgMCksCiAgdHhfcmlza3lfZG9uID0gaWZfZWxzZSh0eCA9PTEgJiBkcnM+NSwgMSwgMCksCiAgdGhyZWVfc3RhdHVzID0gY2FzZV93aGVuKAogICAgc3RhdHVzID09IDIwMTAgfiAiU3RhdHVzIDFBIiwKICAgIHN0YXR1cyA9PSAyMDIwIH4gIlN0YXR1cyAxQiIsCiAgICBzdGF0dXMgPT0gMjAzMCB+ICJTdGF0dXMgMiIKICApCiAgKQpgYGAKCgpJZGVudGlmeSBMVkFEIGNvbXBsaWNhdGlvbnMgdGhhdCBhcmUgbm90IGRldmljZSBtYWxmdW5jdGlvbnMKYGBge3IgbHZhZF9jb21wfQpmaW5hbCA8LSBmaW5hbCAlPiUgbXV0YXRlKAogIGx2YWRfY29tcCA9IGNhc2Vfd2hlbigKICAgIENBTkhYX0FEVUxUX0NSSVRFUklBX0IgPT0xICYgQ0FOSFhfREVWX01BTEZVTkNUTiA9PTEgfiBhcy5udW1lcmljKDApLAogICAgVFJVRSB+IGFzLm51bWVyaWMoQ0FOSFhfQURVTFRfQ1JJVEVSSUFfQikKICApCikKYGBgCgpJZGVudGlmeSBMVkFEIHBhdGllbnRzIGxpc3RlZCB3aXRoIFN0YXR1cyAxQSBlbGVjdGl2ZSB0aW1lCmBgYHtyIGVsZWN0aXZlXzFBLCBlY2hvID0gVFJVRSB9CiMjb2ZmaWNpYWwgU1JUUiBsaXN0IApkdXJhYmxlX2xpc3QgPC0gYygyMDUsIDIwNiwgMjA4LCAyMTAsIDIxNiwgMjE3LCAyMjMsIDIyNCwgMjMwLCAyMzEsIDIzMiwgMjMzLCAKICAgICAgICAgICAgICAgICAgMzA1LCAzMDYsIDMxMywgMzE2LCAzMTksIDMyNSwgNDAyKQpsdmFkX2xpc3QgPC0gYygyMDUsIDIwNiwgMjA4LCAyMTAsIDIxNiwgMjE3LCAyMjMsIDIyNCwgMjMwLCAyMzEsIDIzMiwgMjMzKQpmaW5hbCA8LSBmaW5hbCAlPiVtdXRhdGUoCiAgY2ZfbHZhZCA9IGNhc2Vfd2hlbigKICAgIENBTkhYX0xWQURfVFlQRSAlaW4lIGx2YWRfbGlzdCB+MSwKICAgIENBTl9WQURfVFkgPT0gMiAmIENBTl9WQUQxICVpbiUgbHZhZF9saXN0IH4gMSwKICAgIFJFQ19WQURfVFkgPT0gMiAmIFJFQ19WQUQxICVpbiUgbHZhZF9saXN0IH4gMSwKICAgIENBTkhYX0FEVUxUX0NSSVRFUklBX0I9PTEgfjEsCiAgICBzdGF0dXMgPT0gMjAyMCAmIHN0YWJsZV9sdmFkPT0xIH4gMQogICksCiAgICBlbGVjdGl2ZV8xQSA9IGNhc2Vfd2hlbigKICAgIENBTkhYX0FEVUxUX0NSSVRFUklBX0EgPT0xICYgY2ZfbHZhZCA9PTEgJiBDQU5IWF9JQUJQID09MCAmIENBTkhYX0VDTU8gPT0wIH4gMSwKICAgIENBTkhYX0FEVUxUX0NSSVRFUklBX0IgPT0gMSB+IDAsCiAgICBDQU5IWF9BRFVMVF9DUklURVJJQV9DID09IDEgfiAwLAogICAgQ0FOSFhfQURVTFRfQ1JJVEVSSUFfRCA9PSAxIH4gMCwKICAgIENBTkhYX0FEVUxUX0NSSVRFUklBX0UgPT0gMSB+IDAKICAgICkKKSAKYGBgCgpJZGVudGlmeSB0aW1lIHBlcmlvZHMgd2hlbiBjYW5kaWRhdGUgc3VwcG9ydGVkIHdpdGggYW4gSUFCUCBvciBtdWx0aXBsZSBpbm90cm9wZXMgd291bGQgYmUgZG93bmdyYWRlZCB0byBTdGF0dXMgNCBiYXNlZCBvbiBjYXJkaWFjIGluZGV4LCBwdWxtb25hcnkgY2FwaWxsYXJ5IHdlZGdlIHByZXNzdXJlLCBvciBpbm90cm9wZSBkb3NlLiBTZWUgc3VwcGxlbWVudCBmb3IgbW9yZSBkZXRhaWxzCmBgYHtyIGFkZF9vdmVyX3RyZWF0LCBtZXNzYWdlPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQpmaW5hbCA8LSBmaW5hbCAlPiUgbXV0YXRlKAogIGlub19jaSA9IGFzLm51bWVyaWMoQ0FOSFhfSEVNT19DSSksCglpbm9fcGN3cCA9IGFzLm51bWVyaWMoQ0FOSFhfSEVNT19QQ1dQKSwKICBuX2lub3MgPSBpZmVsc2UoaXMubmEoQ0FOSFhfSU5UUlBfRE9QQSk9PUZBTFNFLCAxLCAwKSArIAogICAgaWZlbHNlKGlzLm5hKENBTkhYX0lOVFJQX0RPQlUpPT1GQUxTRSwgMSwgMCkgKyAKICAgIGlmZWxzZShpcy5uYShDQU5IWF9JTlRSUF9NSUxSSU4pPT1GQUxTRSwgMSwgMCksCiAgbl9pbm9zID0gaWZlbHNlKHN0YXR1cyAhPSAyMDEwLCBOQSwgbl9pbm9zKSwKCW11bHRpX2lubyA9IGlmZWxzZShuX2lub3MgPiAxLCAxLCAwKSwKCXNpbmdsZV9pbm8gPSBpZmVsc2Uobl9pbm9zID09MSwgMSwgMCksCglsb3dfZF9pbm8gPSBpZmVsc2Uobl9pbm9zPiAxICYgCgkgICAgICAgICAgIChDQU5IWF9JTlRSUF9ET1BBPDMgfCBDQU5IWF9JTlRSUF9NSUxSSU4gPDAuMjUgfCBDQU5IWF9JTlRSUF9ET0JVIDwgMyksIDEsIDApLAoJbG93X3NfaW5vID0gaWZlbHNlKG5faW5vcyA9PTEgJiAoQ0FOSFhfSU5UUlBfTUlMUklOIDwwLjUgfCBDQU5IWF9JTlRSUF9ET0JVIDwgNy41KSwxLDApLAogIGJzYSA9IDAuMDA3MTg0KihDQU5fSEdUX0NNKV4oMC43MjUpKkNBTl9XR1RfS0deKDAuNDI1KSwKICB0Y3JfY2kgPSBDQU5fQ0FSRElBQ19PVVRQVVQvYnNhLAogIGlhYnBfbm9fc2hvY2sgPSBjYXNlX3doZW4oCiAgICB0Y3JfY2kgPiAxLjggJiBDQU5fQ0FSRElBQ19PVVRQVVRfTUVEUyA9PSAiTiIgJiAoQ0FOSFhfSUFCUD09MSB8IENBTl9JQUJQID09MSkgfiAxLAogICAgdGNyX2NpID4gMi4wICYgKENBTkhYX0lBQlA9PTEgfCBDQU5fSUFCUCA9PTEpIH4gMSwKICAgIGlzLm5hKHRjcl9jaSkgPT0gRkFMU0UgJiAoQ0FOSFhfSUFCUD09MSB8IENBTl9JQUJQID09MSkgfiAwCiAgKSwKCW92ZXJ0cmVhdCA9IGNhc2Vfd2hlbigKCSAgaWFicF9yZWNfbm9fc2hvY2sgPT0xIH4gMSwKCQlyZWNpcF9vdmVydHJlYXQgPT0gMSB+IDEsCgkJQ0FOX1BDV19NRUFOIDwgMTUgJiBDQU5fSUFCUCA9PTEgfiAxLAoJCUNBTkhYX0hFTU9fUENXUCA8IDE1ICYgQ0FOSFhfQURVTFRfQ1JJVEVSSUFfRCA9PTEgfiAxLAoJCWlub19jaT4yLjJ+IDEsCgkJaW5vX3Bjd3AgPDE1IH4gMSwKCQkoaW5vX2NpPjEuOCAmIENBTkhYX0hFTU9fSU5UUlBfT0JUQUlORUQgPT0iTiIpIH4gMSwKCQlsb3dfZF9pbm8gPT0gMSB8IGxvd19zX2lubyA9PSAxIH4gMSwgCgkJaWFicF9ub19zaG9jayA9PSAxIH4gMSwKCQlpbm9fY2kgPD0gMS44IH4gMCwKCQkoaW5vX2NpIDw9IDIuMiAmIENBTkhYX0hFTU9fSU5UUlBfT0JUQUlORUQgPT0iWSIpIH4gMCwKCQlpYWJwX25vX3Nob2NrID09IDAgfiAwCgkpLAogIG92ZXJfMWEgPSBpZmVsc2Uoc3RhdHVzID09IDIwMjAgfCBzdGF0dXMgPT0gMjAzMCwgMCwgb3ZlcnRyZWF0KQopCgpgYGAKCkNvZGUgc2l4LXN0YXR1cyAKYGBge3IgY29kZV9zaXhfc3RhdHVzfQojbm9uIGRpc2NoYXJnYWJsZSBWQURzCm5vbl9kaXNjaGFyZ2UgPC0gYygyMDEsIDIwMywgMjA0LCAyMDksIDIxNSwgMjE4LCAyMjEsIDIyMiwgMjI1LCAyMjYsIDIyNywgMjI4LCAKICAgICAgICAgICAgICAgICAgIDIzNCwgMzAxLCAzMDIsIDMwMywgMzA5LCAzMTAsIDMxMSwgMzIwLCAzMjEpCgojcmVzdHJpY3RpdmUsIGFteWxvaWQsIENIRCwgYW5kIEhDT00sIGNhcmRpb215b3BhdGh5IGRpYWdub3NlcwpzdGF0NF9kaWFnbm9zZXMgPC0gYygxMDUwLCAxMDUxLCAxMDUyLCAxMDUzLCAxMDU0LCAxMDk5LCAxMTAwLCAxMTAxLCAxMTAyLCAKICAgICAgICAgICAgICAgICAgICAgMTEwMywgMTEwNCwgMTEwNSwgMTEwNiwgMTE5OSwgMTIwMCwgMTIwMSwgMTIwMywgMTIwNSwgMTIwNiwgMTIwNywgMTIwOCkKCgpmaW5hbCA8LSBmaW5hbCAlPiUgZ3JvdXBfYnkoUFhfSUQpICU+JSAKICBtdXRhdGUoZGlhZ25vc2lzID0gbmEubG9jZihDQU5fREdOLCBuYS5ybSA9IEZBTFNFKSkgJT4lCiAgdW5ncm91cCgpCgoKZmluYWwgPC0gZmluYWwgJT4lIG11dGF0ZSgKICBzaXhfc3RhdHVzID0gY2FzZV93aGVuKAogICAgc3RhdHVzID09IDIwMjB+IDQsCiAgICBkaWFnbm9zaXMgJWluJSBzdGF0NF9kaWFnbm9zZXMgJiBzdGF0dXMgPT0yMDMwIH4gNCwKICAgIHN0YXR1cyA9PSAyMDMwfiA2LAogICAgb3ZlcnRyZWF0ID09IDEgfiA0LAogICAgZWxlY3RpdmVfMUEgPT0xIH4gMywKICAgIGx2YWRfY29tcCA9PTEgfjMsCiAgICBDQU5fRUNNTyA9PSAxIH4xLAogICAgQ0FOSFhfRUNNTyA9PSAxIH4gMSwKICAgIFJFQ19FQ01PID09IDEgfiAxLAogICAgQ0FOSFhfQURVTFRfQ1JJVEVSSUFfQSA9PTEgJiBDQU5IWF9SVkFEX1RZUEUgJWluJSBub25fZGlzY2hhcmdlIH4gMSwKICAgIENBTl9WQURfVFkgPT0gNSAmIChDQU5fVkFEMSAlaW4lIG5vbl9kaXNjaGFyZ2UgfCBDQU5fVkFEMiAlaW4lIG5vbl9kaXNjaGFyZ2UpIH4gMSwKICAgIFJFQ19WQURfVFkgPT0gNSAmIChSRUNfVkFEMSAlaW4lIG5vbl9kaXNjaGFyZ2UgfCBSRUNfVkFEMiAlaW4lIG5vbl9kaXNjaGFyZ2UpIH4gMSwKICAgIENBTkhYX0FEVUxUX0NSSVRFUklBX0EgPT0xIH4gMiwKICAgIENBTkhYX0RFVl9NQUxGVU5DVE4gPT0xICB+IDIsCiAgICBDQU5IWF9ERVZfVkVOVF9BUlJZVEhNID09IDEgfiAyLAogICAgc3RhdHVzID09IDIwMTAgJiB0eCA9PTAgfiAzCiAgKSwKICBvdmVyXzFhID0gaWZlbHNlKHNpeF9zdGF0dXMgIT0gNCwgMCwgb3Zlcl8xYSksCiAgZWxlY3RpdmVfMUEgPSBpZmVsc2Uoc2l4X3N0YXR1cyAhPSAzIHwgc3RhdHVzID09IDI5OTksIDAsIGVsZWN0aXZlXzFBKSwKICBsdmFkX2NvbXAgPSBpZmVsc2Uoc2l4X3N0YXR1cyAhPSAzLCAwLCBsdmFkX2NvbXApKSAKCiNjb25maXJtIHRoYXQgdGhlIHN0YXR1cyAyMDEwIHBhdGllbnRzIHJlYXNzaWduZWQgdG8gc3RhdHVzIDQgYXJlIGFsbCBvdmVydHJlYXRlZCAobm90IHJ1bikKI2ZpbmFsICU+JSBmaWx0ZXIoc2l4X3N0YXR1cyA9PTQgJiBzdGF0dXMgPT0yMDEwKSAlPiUgY291bnQob3Zlcl8xYSkKYGBgCgoKQWRkIExWQUQgdmFyaWFibGUKYGBge3IgbHZhZF92YXJpYWJsZX0KZmluYWwgPC0gZmluYWwgJT4lCiAgbXV0YXRlKGx2YWQgPSBjYXNlX3doZW4oCiAgICBsdmFkX2NvbXAgPT0xIH4gMSwKICAgIGVsZWN0aXZlXzFBID09IDEgfiAxLAogICAgc3RhYmxlX2x2YWQgPT0gMSB+IDEKICApKQpgYGAKCgpFeGFtcGxlIGRhdGEgZm9yIGEgcGF0aWVudDoKYGBge3IgZXhhbXBsZV9wYXRpZW50fQpmaW5hbCAlPiUgZmlsdGVyKFBYX0lEID09IDUzMTY4NykgJT4lIAogIHNlbGVjdCh0XzEsIHRfMiwgdHgsIGRlYWQsIHN0YXRfanVzdCwgc2l4X3N0YXR1cywgCiAgICAgICAgIG92ZXJfMWEsIGx2YWRfY29tcCwgZWxlY3RpdmVfMUEpCmBgYApUaGlzIHBhdGllbnQgd2VudCB0aHJvdWdoIHRoZSBmb2xsb3dpbmcgc3RhdHVzIGNoYW5nZXM6CgoqIHN0YXR1cyAxQiB3aXRoIElWIGlub3Ryb3BlcyAoZGF5IDAtMzUpCiogc3RhdHVzIDFBIGV4Y2VwdGlvbiAoY29kZWQgYXMgc2l4LXN0YXR1cyAzKSAoZGF5IDM2LTQxKQoqIHN0YXR1cyAxQiB3aXRoIElWIGlub3Ryb3BlcyAoZGF5IDQyLTE0MCkKKiBzdGF0dXMgMUEgd2l0aCBoaWdoIGRvc2UgSVYgaW5vdHJvcGVzIChyZW1haW5lZCBzaXgtc3RhdHVzIDQgZHVlIHRvIGxhY2sgb2YgY2FyZGlvZ2VuaWMgc2hvY2spIChkYXkgMTQxLTE0OCkKKiBJbmFjdGl2YXRlZCAoZGF5IDE1MC0xNzcpIAoqIHJlLWFjdGl2YXRlZCBhdCBTdGF0dXMgMUEgcy9wIGR1cmFibGUgTFZBRCBpbXBsYW50YXRpb24gd2l0aCBlbGVjdGl2ZSB0aW1lIChzaXgtc3RhdHVzIDMpIChkYXkgMTc4LTE4MSkKKiBJbmFjdGl2YXRlZCAoZGF5IDE4Mi0xOTcpCiogcmUtYWN0aXZhdGVkIGF0IFN0YXR1cyAxQSB3LyBMVkFEIGNvbXBsaWNhdGlvbiAobm90IGRldmljZSBmYWlsdXJlLCBzbyBzaXgtc3RhdHVzIDMpIChkYXkgMTk4LTIwOCkKKiB0cmFuc3BsYW50ZWQgYW5kIHN1cnZpdmVkIGZvciBvdmVyIHRlbiB5ZWFycyAoZGF5IDIwOS0gMzg2MykKCgpXaGVuIHRoZSBjYW5kaWRhdGUgaXMgaW5hY3RpdmF0ZWQgZnJvbSB0aGUgbGlzdCwgd2UgY2FycnkgZm9yd2FyZCB0aGVpciBzdGF0dXMgZnJvbSB0aGUgcHJldmlvdXMgb2JzZXJ2ZWQgcGVyaW9kLiBCZWNhdXNlIG1hbnkgY2FuZGlkYXRlcyBhcmUgZGVhY3RpdmF0ZWQgZnJvbSBsaXN0IGJlZm9yZSBkeWluZywgdGhpcyBhc3N1bXB0aW9uIGFsbG93cyB0aGUgbW9kZWwgdG8gYXBwcm9wcmlhdGVseSBjYXB0dXJlIHRoZSByaXNrIG9mIGVhY2ggYWN0aXZlIHdhaXRsaXN0IHN0YXR1cy4KYGBge3IgY2FycnlfZm9yd2FyZH0KI2NhcnJ5IGZvcndhcmQgc3RhdHVzZXMgdG8gZmlsbCBpbmFjdGl2ZSBwZXJpb2RzCmRhdGEgPC0gZmluYWwgJT4lIAogIGFycmFuZ2UoUFhfSUQsIHRfMSkgJT4lIGdyb3VwX2J5KFBYX0lEKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoc2l4X3N0YXR1cywgc3RhdF9qdXN0LCB0aHJlZV9zdGF0dXMsIAogICAgICAgICAgICAgICAgIG92ZXJfMWEsIGxpc3RfeWVhciwgCiAgICAgICAgICAgICAgICAgbHZhZF9jb21wLCBlbGVjdGl2ZV8xQSwgY2ZfbHZhZCwgCiAgICAgICAgICAgICAgICAgYmxvb2RfdHlwZSwgYWdlLCBmZW1hbGUsIGJtaV9sb3csIAogICAgICAgICAgICAgICAgIGJtaV9oaWdoLCBzaW1wbGVfZGlhZywgY3Jvc3NfbWF0Y2gpLCAKICAgICAgICAgICAgbGlzdCh+bmEubG9jZiguLCBuYS5ybSA9IEZBTFNFKSkpICU+JSAKICB1bmdyb3VwKCkKCgpgYGAKCkV4YW1wbGUgZGF0YSBmb3IgYSBwYXRpZW50IHdpdGggc3RhdHVzZXMgImNhcnJpZWQgZm9yd2FyZCIKYGBge3IgZXhhbXBsZV93aXRoX2ZpbGxlZF9pbl9zdGF0dXN9CmRhdGEgJT4lIGZpbHRlcihQWF9JRCA9PSA1MzE2ODcpICU+JSAKICBzZWxlY3QodF8xLCB0XzIsIHR4LCBkZWFkLCAKICAgICAgICAgc3RhdF9qdXN0LCBzaXhfc3RhdHVzLCBvdmVyXzFhLCAKICAgICAgICAgbHZhZF9jb21wLCBlbGVjdGl2ZV8xQSwgY2ZfbHZhZCwgCiAgICAgICAgIGFnZSwgZmVtYWxlLCBibGFjaywgCiAgICAgICAgIGJtaV9sb3csIGJtaV9oaWdoLCBkaWFnbm9zaXMsIGNyb3NzX21hdGNoKQpgYGAKCgoKYGBge3J9CmRhdGEgJT4lIHNlbGVjdChQWF9JRCwgdF8xLCB0XzIsIHR4LCBkZWFkLCBzdGF0X2p1c3QsIGNmX2x2YWQpCmBgYAoKCkZvciB0aGUgYHIgZGF0YSAlPiUgZmlsdGVyKHR4ID09MSAmIHRfMSA9PTEpICU+JSBucm93KClgIHJlY2lwaWVudHMgd2l0aCBvbmx5IG9uZSBvYnNlcnZhdGlvbiwgYXNzaWduIHRoZW0gc3RhdHVzIHRocmVlIGZvciAxQSwgZm91ciBmb3IgMUIsIGFuZCBzaXggZm9yIDIuCmBgYHtyIHR4X29ubHl9CmRhdGEgPC0gZGF0YSAlPiUKICBtdXRhdGUoCiAgICBzaXhfc3RhdHVzID0gY2FzZV93aGVuKAogICAgICB0eCA9PTEgJiBpcy5uYShzaXhfc3RhdHVzKSAmIHRocmVlX3N0YXR1cyA9PSAiU3RhdHVzIDFBIiB+IDMsCiAgICAgIHR4ID09MSAmIGlzLm5hKHNpeF9zdGF0dXMpICYgdGhyZWVfc3RhdHVzID09ICJTdGF0dXMgMUIiIH4gNCwKICAgICAgdHggPT0xICYgaXMubmEoc2l4X3N0YXR1cykgJiB0aHJlZV9zdGF0dXMgPT0gIlN0YXR1cyAyIiB+IDYsCiAgICAgIFRSVUUgfiBzaXhfc3RhdHVzCiAgICApCiAgKQpgYGAKCgpgYGB7ciBkdW1teV9jb2RlfQojZHVtbXkgY29kZSBzdGF0dXNlcwpkYXRhIDwtIGRhdGEgJT4lCiAgbXV0YXRlKAogICAgc3RhdF8xYSA9IGlmZWxzZSh0aHJlZV9zdGF0dXMgPT0gIlN0YXR1cyAxQSIsIDEsIDApLAogICAgc3RhdF8xYiA9IGlmZWxzZSh0aHJlZV9zdGF0dXMgPT0iU3RhdHVzIDFCIiwgMSwwKSwKICAgIHN0YXRfMiA9IGlmZWxzZSh0aHJlZV9zdGF0dXMgPT0gIlN0YXR1cyAyIiwgMSwgMCksIAogICAgc3RhdHVzXzEgPSBpZmVsc2Uoc2l4X3N0YXR1cyA9PSAxLCAxLCAwKSwKICAgIHN0YXR1c18yID0gaWZlbHNlKHNpeF9zdGF0dXMgPT0gMiwgMSwgMCksCiAgICBzdGF0dXNfMyA9IGlmZWxzZShzaXhfc3RhdHVzID09IDMsIDEsIDApLAogICAgc3RhdHVzXzQgPSBpZmVsc2Uoc2l4X3N0YXR1cyA9PSA0LCAxLCAwKSwKICAgIHN0YXR1c182ID0gaWZlbHNlKHNpeF9zdGF0dXMgPT0gNiwgMSwgMCkKICApCmBgYAoKCiMgQ3JlYXRlIGFuYWx5dGljIGRhdGFzZXQgZm9yIHRoZSBtb2RlbCBhbmQgd3JpdGUgb3V0IGFzIGNzdiBmaWxlCmBgYHtyIGNyZWF0ZV9vdXRmaWxlfQp0b19tb2RlbCA8LSBkYXRhICU+JSAKICBzZWxlY3QoUFhfSUQsIGNlbnRlciwgT1BPLCB0XzEsIHRfMiwgdHgsIGRlYWQsIHN0YXRfMWEsIHN0YXRfMWIsIHN0YXRfMiwgCiAgICAgICAgIHN0YXR1c18xLCBzdGF0dXNfMiwgc3RhdHVzXzMsIHN0YXR1c180LCBzdGF0dXNfNiwgCiAgICAgICAgIHN0YXRfanVzdCwgdGhyZWVfc3RhdHVzLCBzaXhfc3RhdHVzLAogICAgICAgICBjZl9sdmFkLAogICAgICAgICBlcmFfdHgsIHR4X3Jpc2t5X2RvbiwKICAgICAgICAgRE9OX0JVTiwgRE9OX0NSRUFULCBET05fQUdFLCBSRUNfSFJfSVNDSCwgCiAgICAgICAgIGJsYWNrLCBibGFja19kb24sCiAgICAgICAgIGxpc3RfeWVhciwKICAgICAgICAgYWdlLCBmZW1hbGUsIGJsb29kX3R5cGUsIGJtaV9sb3csIGJtaV9oaWdoLCBzaW1wbGVfZGlhZywgY3Jvc3NfbWF0Y2gpICU+JQogIG11dGF0ZV9hdCh2YXJzKGNmX2x2YWQsIGJsYWNrLCBibGFja19kb24sIFJFQ19IUl9JU0NILCBET05fQlVOLCBET05fQ1JFQVQsIERPTl9BR0UpLCAKICAgICAgICAgICAgbGlzdCh+aWZlbHNlKGlzLm5hKC4pPT1UUlVFLCAwLCAuKSkpJT4lCiAgZHJvcF9uYShzdGF0XzFhKSAjI0tleSBmaWx0ZXIgc3RlcCwgcmVtb3ZlcyBwYXRpZW50cyB3aG8gd2VyZSBuZXZlciBhY3RpdmF0ZWQKCiMgbm90IHJ1bi0gY29uZmlybSBkcm9wcGVkIHBhdGllbnRzIHdlcmUgbmV2ZXIgYWN0aXZhdGVkIG9uIHRoZSB3YWl0bGlzdAojIGRhdGEgJT4lIAojICAgZ3JvdXBfYnkoUFhfSUQpICU+JQojICAgY291bnQoc3RhdF9qdXN0KSAlPiUKIyAgIG11dGF0ZSh0b3RhbF9qdXN0cyA9IHN1bShuKSkgJT4lCiMgICBzcHJlYWQoa2V5ID0gc3RhdF9qdXN0LCB2YWx1ZSA9IG4pICU+JQojICAgZmlsdGVyKHRvdGFsX2p1c3RzID09IEluYWN0aXZlKQpgYGAKCgpgYGB7ciBjZW50ZXJfcmVnaW9ufQpjZW50ZXJfcmVnaW9uIDwtIGluc3RpdHV0aW9uICU+JSAKICBmaWx0ZXIoQ1RSX1RZICVpbiUgYygiVFgxIiwgIlZBMSIsICJGVFgiKSkgJT4lIAogIHNlbGVjdChDVFJfSUQsIFJFR0lPTikgJT4lCiAgcmVuYW1lKGNlbnRlcj0gQ1RSX0lEKQoKdG9fbW9kZWwgPC0gdG9fbW9kZWwgJT4lIGxlZnRfam9pbihjZW50ZXJfcmVnaW9uLCBieSA9ICJjZW50ZXIiKQpgYGAKCmBgYHtyIG91dGZpbGUsIGVjaG8gPSBUUlVFfQojd3JpdGUgZmluYWwgZGF0YSBzZXQgb3V0IGFzIGEgY3N2IGZpbGUKd3JpdGVfY3N2KHRvX21vZGVsLCBvdXRmaWxlKQpgYGAKCgojIyBTaXgtc3RhdHVzIHN5c3RlbSBjb2Rpbmcgc3VtbWFyeSBmb3IgYWxsIG9ic2VydmF0aW9ucwpgYGB7ciBzdGF0dXNfc3dpdGNoX3RhYmxlfQpmdGFibGUodG9fbW9kZWwkc3RhdF9qdXN0LCB0b19tb2RlbCRzaXhfc3RhdHVzKQpgYGAKTm90ZTogVGhlIGNhbmRpZGF0ZXMgd2l0aCBleGNlcHRpb25zLCBoaWdoIGRvc2UgaW5vdHJvcGVzLCBvciBtZWNoYW5pY2FsIHZlbnRpbGF0aW9uIHdobyBNQ1MgY29tcGxpY2F0aW9ucyB3aG8gd2VyZSBjb2RlZCBhcyBTdGF0dXMgMSBtZXQgdGhlIGNyaXRlcmlhIGJlY2F1c2UgaGFkIGEgTUNTRCB3aXRoIGxpZmUtdGhyZWF0ZW5pbmcgdmVudHJpY3VsYXIgYXJyaHl0aG1pYSwgb3Igd2VyZSBzdXBwb3J0ZWQgYnkgVkEgRUNNTyBvciBOb24tZGlzY2hhcmdlYWJsZSwgc3VyZ2ljYWxseSBpbXBsYW50ZWQsIG5vbi1lbmRvdmFzY3VsYXIgYmktdmVudHJpY3VsYXIgc3VwcG9ydCBkZXZpY2UuCgojI1NpeC1zdGF0dXMgc3lzdGVtIGNvZGluZyBzdW1tYXJ5IGZvciBhbGwgcmVjaXBpZW50cwpgYGB7ciBzdGF0dXNfc3dpdGNoX3RhYmxlX3JlY2lwc19kZXRhaWx9CnJlY2lwcyA8LSB0b19tb2RlbCAlPiUgZmlsdGVyKHR4ID09MSkKZnRhYmxlKHJlY2lwcyRzdGF0X2p1c3QsIHJlY2lwcyRzaXhfc3RhdHVzKQpgYGAKCgpgYGB7ciBzdGF0dXNfc3dpdGNoX25vX2RldGFpbH0KZnRhYmxlKHJlY2lwcyRzaXhfc3RhdHVzLCByZWNpcHMkdGhyZWVfc3RhdHVzKQoKdG9fbW9kZWwgJT4lIHNlbGVjdChQWF9JRCwgdF8xLCB0XzIsIHR4LCBkZWFkLCBzdGF0X2p1c3QsIGNmX2x2YWQpCmBgYAoKClxwYWdlYnJlYWsKCiMgUmVzdWx0czogKlN0dWR5IFBvcHVsYXRpb24qCmBgYHtyIHNpbXBsZV9mbG93fQoKCiNjYWxjdWxhdGUgdmFsdWVzIGZvciBmbG93LWNoYXJ0CnRvdF9hbmFseXplZCA8LSB0b19tb2RlbCAlPiUgZ3JvdXBfYnkoUFhfSUQpICU+JSBmaWx0ZXIocm93X251bWJlcigpPT0xKSAlPiUgdW5ncm91cCgpICU+JSBucm93KCkKCm1pc3NfZGF0YSA8LSBucm93KGluaXRfbGlzdCkgLSB0b3RfYW5hbHl6ZWQKCiNtaXNzaW5nIGRhdGEgZXhjbHVzaW9uIGRldGFpbAp0b3RhbF9leGNsdXNpb25zIDwtIHRvdF9hZHVsdHMgLSB0b3RfYW5hbHl6ZWQKCgojI2lkZW50aWZ5IGNhbmRpZGF0ZXMgd2hvIHdlcmUgbmV2ZXIgYWN0aXZlCm9ubHlfaW5hY3RpdmUgPC0gZGF0YSAlPiUgCiAgZ3JvdXBfYnkoUFhfSUQpICU+JSBzdW1tYXJpc2UobWVhbl9zdGF0ID0gbWluKHN0YXR1cykpICU+JSAKICBmaWx0ZXIobWVhbl9zdGF0ID09IDI5OTkpICU+JSB1bmdyb3VwKCkgJT4lIG5yb3coKQoKIyNyZW1haW5pbmcgY2FuZGlkYXRlcyBoYWQgZXJyb25lb3VzIGRhdGVzCmVycm9yX2RhdGVzIDwtIGluaXRfbGlzdCAlPiUgZmlsdGVyKCFQWF9JRCAlaW4lIGRhdGEkUFhfSUQpCmVycm9yX2RhdGVzIDwtIGxlbmd0aCh1bmlxdWUoZXJyb3JfZGF0ZXMkUFhfSUQpKQoKCiNvdXRjb21lcwoKIyN0b3RhbCBkZWF0aHMgd2l0aG91dCB0cmFuc3BsYW50CmRpZWRfYmVmb3JlX3R4IDwtIHRvX21vZGVsICU+JSAKICBncm91cF9ieShQWF9JRCkgJT4lIAogIGZpbHRlcihyb3dfbnVtYmVyKCk9PSBuKCkpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcih0eCA9PTAgJiBkZWFkID09MSkgJT4lIG5yb3coKQoKIyNkZWF0aHMgd2hpbGUgc3RpbGwgYWN0aXZlIG9uIGxpc3QKZGVhdGhfb25fbGlzdCA8LSBkYXRhICU+JSAKICBmaWx0ZXIoUFhfSUQgJWluJSB0b19tb2RlbCRQWF9JRCkgJT4lIAogIGdyb3VwX2J5KFBYX0lEKSAlPiUgCiAgZmlsdGVyKHJvd19udW1iZXIoKT09MSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKENBTl9SRU1fQ0QuaW5pdCA9PSA4KSAlPiUKICBucm93KCkKCiMjZGVhdGhzIGFmdGVyIGRlbGlzdGluZwpkaWVkX2RlbGlzdCA8LSBkaWVkX2JlZm9yZV90eCAtIGRlYXRoX29uX2xpc3QKCiMjdHJhbnNwbGFudGVkCnRvdF90eCA8LSByZWNpcHMgJT4lIG5yb3coKQoKIyNzdGlsbCB3YWl0aW5nIGF0IGVuZCBvZiBmb2xsb3ctdXAKc3RpbGxfd2FpdGluZyA8LXRvdF9hbmFseXplZCAtIHRvdF90eCAtIGRpZWRfYmVmb3JlX3R4CgojUG9zdC10cmFuc3BsYW50IG91dGNvbWVzCiMjZGVhZCBvciByZS10cmFuc3BsYW50ZWQgcG9zdC10cmFuc3BsYW50CmRlYWRfcG9zdF90eCA8LSByZWNpcHMgJT4lIGZpbHRlcihkZWFkID09MSkgJT4lIG5yb3coKQoKIyNyZS10cmFuc3BsYW50CnBvc3RfdHhfcmVfdHggPC0gZGF0YSAlPiUgCiAgZmlsdGVyKFBYX0lEICVpbiUgdG9fbW9kZWwkUFhfSUQpICU+JSAKICBncm91cF9ieShQWF9JRCkgJT4lIAogIGZpbHRlcih0eCA9PSAxKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoVEZMX0xBU1RBVFVTID09ICJSIikgJT4lCiAgbnJvdygpCgojI2RlYXRocwpwb3N0X3R4X2RlYXRocyA8LSBkZWFkX3Bvc3RfdHggLSBwb3N0X3R4X3JlX3R4CgojI2FsaXZlIHBvc3QtdHJhbnNwbGFudAphbGl2ZV9wb3N0X3R4IDwtIHJlY2lwcyAlPiUgZmlsdGVyKGRlYWQgPT0gMCkgJT4lIG5yb3coKQoKCiMjY2FsY3VsYXRlIG1lYW4gZm9sbG93LXVwIHRpbWUgZm9yIGNlbnNvcmVkIG9ic2VydmF0aW9ucwpsYXN0X29iIDwtIHRvX21vZGVsICU+JSAKICBncm91cF9ieShQWF9JRCkgJT4lIGFycmFuZ2UodF8xKSAlPiUgCiAgZmlsdGVyKGRlYWQgPT0wICYgcm93X251bWJlcigpID09IG4oKSkgJT4lIAogIHNlbGVjdChQWF9JRCwgdF8yKQoKbWVhbl9mdXBfdGltZSA8LSBjb21tYV8yKG1lYW4obGFzdF9vYiR0XzIpLzM2NSkKYGBgCkR1cmluZyAyMDA2LTIwMTUsIHRoZXJlIHdlcmUgYHIgY29tbWEodG90X2FkdWx0cylgIGFkdWx0IGNhbmRpZGF0ZXMgcmVnaXN0ZXJlZCBmb3IgaGVhcnQgdHJhbnNwbGFudGF0aW9uIGluIHRoZSBVUy4gQWZ0ZXIgZXhjbHVzaW9ucyAoKipGaWd1cmUgMSoqKSwgdGhlIHJlbWFpbmluZyBlbGlnaWJsZSBgciBjb21tYSh0b3RfYW5hbHl6ZWQpYCBhZHVsdCBjYW5kaWRhdGVzIHdlcmUgbGlzdGVkIGF0IGByIGxlbmd0aCh1bmlxdWUodG9fbW9kZWwkY2VudGVyKSlgIGNlbnRlcnMgYW5kIGByIGNvbW1hKHRvdF90eClgIChgciBjb21tYV8yKDEwMCp0b3RfdHgvdG90X2FuYWx5emVkKWAlKSByZWNlaXZlZCBhIGhlYXJ0IHRyYW5zcGxhbnQuIEFtb25nIGhlYXJ0IHRyYW5zcGxhbnQgcmVjaXBpZW50cywgYHIgY29tbWEoZGVhZF9wb3N0X3R4KWAgKGByIGNvbW1hXzIoMTAwKmRlYWRfcG9zdF90eC90b3RfdHgpYCUpIGRpZWQgb3Igd2VyZSByZS10cmFuc3BsYW50ZWQgZHVyaW5nIHRoZSBzdHVkeSBwZXJpb2QgYW5kIGByIGNvbW1hKGFsaXZlX3Bvc3RfdHgpYCAoYHIgY29tbWFfMigxMDAqYWxpdmVfcG9zdF90eC90b3RfdHgpYCUpIHJlbWFpbmVkIGFsaXZlIGF0IGxhc3QgZm9sbG93LXVwLiBPZiB0aGUgYHIgY29tbWEodG90X2FuYWx5emVkIC0gdG90X3R4KWAgY2FuZGlkYXRlcyB3aG8gZGlkIG5vdCByZWNlaXZlIGEgdHJhbnNwbGFudCwgYHIgY29tbWEoZGllZF9iZWZvcmVfdHgpYCAoYHIgY29tbWFfMigxMDAqZGllZF9iZWZvcmVfdHgvKHRvdF9hbmFseXplZCAtIHRvdF90eCkpYCUpIGRpZWQgKGByIGNvbW1hKGRlYXRoX29uX2xpc3QpYCB3aGlsZSBvbiB0aGUgd2FpdGxpc3QgYW5kIGByIGNvbW1hKGRpZWRfZGVsaXN0KWAgYWZ0ZXIgZGVsaXN0aW5nKSBhbmQgYHIgY29tbWEoc3RpbGxfd2FpdGluZylgIChgciBjb21tYV8yKDEwMCpzdGlsbF93YWl0aW5nLyh0b3RfYW5hbHl6ZWQgLSB0b3RfdHgpKWAlKSB3ZXJlIGFsaXZlIGJ1dCBoYWQgbm90IHJlY2VpdmVkIGEgdHJhbnNwbGFudCBieSB0aGUgZW5kIG9mIGZvbGxvdy11cC4gU3Vydml2aW5nIHBhdGllbnRzIGluIHRoZSBjb2hvcnQgd2VyZSBmb2xsb3dlZCBmb3IgYW4gYXZlcmFnZSBvZiBgciBtZWFuX2Z1cF90aW1lYCB5ZWFycyBiZWZvcmUgY2Vuc29yaW5nLgoKIyMgRmlndXJlIDE6IFNUUk9CRSBmbG93IGRpYWdyYW0KIVtdKEZpZ3VyZV8xXzIwMTgucG5nKQoKU3R1ZHkgcG9wdWxhdGlvbiBzZWxlY3Rpb24gZGlzcGxheWVkIGluIFNUcmVuZ3RoZW5pbmcgdGhlIFJlcG9ydGluZyBvZiBPQnNlcnZhdGlvbmFsIHN0dWRpZXMgaW4gRXBpZGVtaW9sb2d5IChTVFJPQkUpIGRpYWdyYW0gZm9ybWF0LiAKV2UgZXhjbHVkZWQgYHIgY29tbWEobl9tdWx0cylgIGZvciBtdWx0aS1vcmdhbiB0cmFuc3BsYW50YXRpb24sIGByIGNvbW1hKHJlbW92ZWRfbG93X3R4KWAgY2FuZGlkYXRlcyBmb3IgbGlzdGluZyBhdCBvbmUgb2YgYHIgbnVtX2xvd192b2xfY2VudGVyc2AgbG93IHZvbHVtZSBjZW50ZXJzLCBgciBjb21tYShvbmx5X2luYWN0aXZlKWAgY2FuZGlkYXRlcyB3aG8gd2VyZSBuZXZlciBhY3RpdmF0ZWQgb24gdGhlIGxpc3QsIGFuZCBgciBjb21tYShlcnJvcl9kYXRlcylgIGNhbmRpZGF0ZXMgd2l0aCBvYnZpb3VzIGRhdGEgZW50cnkuCgoKKiBUaGVyZSB3ZXJlIGByIGNvbW1hKHRvdF9hZHVsdHMpYCBhZHVsdCBoZWFydCB0cmFuc3BsYW50IGNhbmRpZGF0ZXMgbGlzdGVkIGZyb20gMjAwNi0yMDE1CiogQWZ0ZXIgYXBwbHlpbmcgZXhjbHVzaW9uIGNyaXRlcmlhLCB0aGUgdG90YWwgbnVtYmVyIG9mIGNhbmRpZGF0ZXMgYW5hbHl6ZWQgd2FzIGByIGNvbW1hKHRvdF9hbmFseXplZClgCiogVGhlcmUgd2VyZSBgciBjb21tYSh0b3RhbF9leGNsdXNpb25zKWAgRXhjbHVzaW9ucwogICAgKiBtdWx0aS1vcmdhbiB0cmFuc3BsYW50IGByIGNvbW1hKG5fbXVsdHMpYAogICAgKiBsb3ctdm9sdW1lIGNlbnRlciBgciBjb21tYShyZW1vdmVkX2xvd190eClgCiAgICAqIG1pc3NpbmcgZGF0YSBgciBjb21tYShtaXNzX2RhdGEpYAogICAgICAgICogYHIgY29tbWEob25seV9pbmFjdGl2ZSlgIGV4Y2x1c2lvbnMgZm9yIGNhbmRpZGF0ZXMgd2hvIHdlcmUgbmV2ZXIgYWN0aXZhdGVkIG9uIHRoZSBsaXN0CiAgICAgICAgKiBgciBjb21tYShlcnJvcl9kYXRlcylgIGNhbmRpZGF0ZXMgd2l0aCBvYnZpb3VzIGRhdGUgZGF0YSBlbnRyeSBlcnJvcnMKKiBBIHRvdGFsIG9mIGByIGNvbW1hKHRvdF9hbmFseXplZCAtIHRvdF90eClgIGNhbmRpZGF0ZXMgd2VyZSBub3QgdHJhbnNwbGFudGVkCiAgICAqIGByIGNvbW1hKGRpZWRfYmVmb3JlX3R4KWAgY2FuZGlkYXRlcyBkaWVkIGJlZm9yZSB0cmFuc3BsYW50CiAgICAgICAgKiBkZWF0aCBvbiB3YWl0bGlzdCAoTj0gYHIgY29tbWEoZGVhdGhfb25fbGlzdClgKQogICAgICAgICogZGllZCBhZnRlciBkZWxpc3RpbmcgKE4gPSBgciBjb21tYShkaWVkX2RlbGlzdClgKQogICAgKiBgciBjb21tYShzdGlsbF93YWl0aW5nKWAgY2FuZGlkYXRlcyBkaWQgbm90IHJlY2VpdmUgYSB0cmFuc3BsYW50IGJlZm9yZSB0aGUgZW5kIG9mIGZvbGxvdy11cAoqIFRoZXJlIHdlcmUgYHIgY29tbWEodG90X3R4KWAgdG90YWwgdHJhbnNwbGFudHMKICAgICogQSB0b3RhbCBvZiBgciBjb21tYShkZWFkX3Bvc3RfdHgpYCByZWNpcGllbnRzIGRpZWQgb3Igd2VyZSByZS10cmFuc3BsYW50ZWQKICAgICAgICAqIHBvc3QtdHJhbnNwbGFudCBkZWF0aCAoTiA9IGByIGNvbW1hKHBvc3RfdHhfZGVhdGhzKWApCiAgICAgICAgKiByZS10cmFuc3BsYW50KE4gPSBgciBjb21tYShwb3N0X3R4X3JlX3R4KWApCiAgICAqIFRoZSByZW1haW5pbmcgYHIgY29tbWEoYWxpdmVfcG9zdF90eClgIHJlY2lwaWVudHMgcmVtYWluZWQgYWxpdmUgYXQgbGFzdCBmb2xsb3ctdXAgCiAgICAKCiMgVGFibGUgMQpgYGB7ciB0YWJsZV8xfQpsaWJyYXJ5KHRhYmxlb25lKQoKY2FuZF90aG9yIDwtIHJlYWRfc2FzKCJTQUYgMjAxOCBRMy9jYW5kX3Rob3Iuc2FzN2JkYXQiLCBOVUxMKSAlPiUgIAogIHphcF9mb3JtYXRzKCkgJT4lIHphcF9sYWJlbHMoKQoKZm9yX3RhYmxlX29uZSA8LSB0b19tb2RlbCAlPiUgCiAgZ3JvdXBfYnkoUFhfSUQpICU+JQogIG11dGF0ZSh0eF9tZWFuID0gbWVhbih0eCksCiAgICAgICAgIGdvdF90eCA9IGlmZWxzZSh0eF9tZWFuPiAwLCAxLCAwKSkgJT4lCiAgZmlsdGVyKHJvd19udW1iZXIoKT09MSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGxlZnRfam9pbihjYW5kX3Rob3IpCgpmb3JfdGFibGVfb25lIDwtIGZvcl90YWJsZV9vbmUgJT4lCiAgc2VsZWN0KAogICAgQ0FOX0FHRV9BVF9MSVNUSU5HLAogICAgQ0FOX0dFTkRFUiwKICAgIENBTl9CTUksCiAgICBDQU5fUkFDRSwKICAgIENBTl9ER04sCiAgICBDQU5fQUJPLAogICAgQ0FOX0RJQUJfVFksCiAgICBDQU5fTU9TVF9SRUNFTlRfQ1JFQVQsCiAgICBDQU5fRElBTCwKICAgIENBTl9GVU5DVE5fU1RBVCwKICAgIENBTl9QQ1dfTUVBTiwKICAgIENBTl9QVUxNX0FSVF9NRUFOLAogICAgQ0FOX0NBUkRJQUNfT1VUUFVULAogICAgQ0FOX1dHVF9LRywKICAgIENBTl9IR1RfQ00sCiAgICBDQU5fUFJJTUFSWV9QQVksCiAgICBzdGF0X2p1c3QsCiAgICBjZl9sdmFkLAogICAgZ290X3R4KSAlPiUKICAgbXV0YXRlKEdlbmRlciA9IGZhY3RvcihDQU5fR0VOREVSLCBsZXZlbHMgPSBjKCJGIiwgIk0iKSksCiAgICAgICAgIFJhY2UgPSBmYWN0b3IoQ0FOX1JBQ0UpLAogICAgICAgICBSYWNlID0gZmN0X2x1bXAoUmFjZSwgbiA9IDMpLAogICAgICAgIFJhY2UgPSBmY3RfcmVjb2RlKFJhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIldoaXRlIiA9ICI4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAiQmxhY2siID0gIjE2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAiSGlzcGFuaWMiID0gIjIwMDAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAiT3RoZXIiID0gIk90aGVyIiksCiAgICAgICAgRGlhZ25vc2lzID0gY2FzZV93aGVuKAogICAgICAgICAgQ0FOX0RHTj45OTkgJiBDQU5fREdOPDEwMDcgfiAiRGlsYXRlZCBjYXJkaW9teW9wYXRoeSwgbm9uLWlzY2hlbWljIiwKICAgICAgICAgIENBTl9ER04gPT0gMTAwNyB8IENBTl9ER04gPT0xMjAwIH4gIklzY2hlbWljIGNhcmRpb215b3BhdGh5IiwKICAgICAgICAgIENBTl9ER04+MTA0OCAmIENBTl9ER048IDExMDAgfiAiUmVzdHJpY3RpdmUgY2FyZGlvbXlvcGF0aHkiLAogICAgICAgICAgVFJVRSB+ICJPdGhlciIKICAgICAgICApLAogICAgICAgIERpYWdub3NpcyA9IGZhY3RvcihEaWFnbm9zaXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJEaWxhdGVkIGNhcmRpb215b3BhdGh5LCBub24taXNjaGVtaWMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSXNjaGVtaWMgY2FyZGlvbXlvcGF0aHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVzdHJpY3RpdmUgY2FyZGlvbXlvcGF0aHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT3RoZXIiKSksCiAgICAgICAgRGlhYmV0ZXMgPSBjYXNlX3doZW4oCiAgICAgICAgICBDQU5fRElBQl9UWT4xICYgQ0FOX0RJQUJfVFk8NiB+ICJIaXN0b3J5IG9mIERNIiwKICAgICAgICAgIENBTl9ESUFCX1RZID09MSB+ICJOb24tZGlhYmV0aWMiLAogICAgICAgICAgVFJVRSB+ICJVbmtub3duIgogICAgICAgICksCiAgICAgICAgZmVtYWxlX2dmciA9IGlmX2Vsc2UoQ0FOX0dFTkRFUiA9PSAiRiIsIDAuNzQyLCAxKSwKICAgICAgICBibGFja19nZnIgPSBpZl9lbHNlKFJhY2UgPT0gIkJsYWNrIiwgMS4yMSwgMSksCmVHRlIgPSAxNzUqKChDQU5fTU9TVF9SRUNFTlRfQ1JFQVQpXigtMS4xNTQpKSooQ0FOX0FHRV9BVF9MSVNUSU5HXigtMC4yMDMpKSpmZW1hbGVfZ2ZyKmJsYWNrX2dmciwKICAgICAgICBSZW5hbF9GdW5jdGlvbiA9IGNhc2Vfd2hlbigKICAgICAgICAgIENBTl9ESUFMID09ICJZIiB+ICJEaWFseXNpcyIsCiAgICAgICAgICBlR0ZSID49IDYwIH4gIkdGUiA+PSA2MCBtbC9taW4vMS43MyBtXjIiLAogICAgICAgICAgZUdGUj49IDMwIH4gIkdGUiA+PSAzMCAmIDw2MCBtbC9taW4vMS43MyBtXjIiLAogICAgICAgICAgZUdGUiA8IDMwIH4gIkdGUiA8IDMwIG1sL21pbi8xLjczIG1eMiIsCiAgICAgICAgICBUUlVFIH4gIlVua25vd24iCiAgICAgICAgKSwKICAgICAgICBSZW5hbF9GdW5jdGlvbiA9IGlmX2Vsc2UoaXMubmEoUmVuYWxfRnVuY3Rpb24pPT1UUlVFLCAiVW5rbm93biIsIFJlbmFsX0Z1bmN0aW9uKSwKICAgICAgICBib2R5X3N1cmZhY2VfYXJlYSA9IDAuMDA3MTg0KihDQU5fSEdUX0NNKV4oMC43MjUpKkNBTl9XR1RfS0deKDAuNDI1KSwKICAgICAgICBDYXJkaWFjX0luZGV4ID0gYXMubnVtZXJpYyhDQU5fQ0FSRElBQ19PVVRQVVQvYm9keV9zdXJmYWNlX2FyZWEpLAogICAgICAgIEZ1bmN0aW9uYWxfU3RhdHVzID0gY2FzZV93aGVuKAogICAgICAgICAgQ0FOX0ZVTkNUTl9TVEFUID09IDEgfCAoQ0FOX0ZVTkNUTl9TVEFUPjIwNjkpIH4iTGltaXRlZCBJbXBhaXJtZW50LCAxMC0zMCUiLAogICAgICAgICAgKENBTl9GVU5DVE5fU1RBVD4yMDM5ICYgQ0FOX0ZVTkNUTl9TVEFUPDIwNjEpIH4gIk1vZGVyYXRlIEltcGFpcm1lbnQsIDQwLTYwJSIsCiAgICAgICAgICAoQ0FOX0ZVTkNUTl9TVEFUPjIwMDAgJiBDQU5fRlVOQ1ROX1NUQVQ8MjAzMSkgfiAiU2V2ZXJlIEltcGFpcm1lbnQsIDcwLTEwMCUiLAogICAgICAgICAgVFJVRSB+ICJVbmtub3duIgogICAgICAgICksCiAgICAgICAgRnVuY3Rpb25hbF9TdGF0dXMgPSBpZmVsc2UoaXMubmEoRnVuY3Rpb25hbF9TdGF0dXMpLCAiVW5rbm93biIsIEZ1bmN0aW9uYWxfU3RhdHVzKSwKICAgICAgICBzZXZlcmVfaW1wYWlybWVudCA9IGlmZWxzZShGdW5jdGlvbmFsX1N0YXR1cyA9PSAiU2V2ZXJlIEltcGFpcm1lbnQsIDcwLTEwMCUiLCAxLCAwKSwKICAgICAgICBhY3V0ZV9tY3MgPSBpZmVsc2Uoc3RhdF9qdXN0ID09ICJTdGF0dXMgMUEgKE1DUyBmb3Igc2hvY2spIiwgMSwgMCksCiAgICAgICAgbHZhZF9jb21wID0gaWZlbHNlKHN0YXRfanVzdCA9PSAiU3RhdHVzIDFBIChNQ1MgY29tcGxpY2F0aW9uKSIsIDEsIDApLAogICAgICAgIHBjd3BfMTUgPSBpZmVsc2UoQ0FOX1BDV19NRUFOIDwgMTUsIDEsIDApLAogICAgICAgIHBjd3BfMTUgPSBpZmVsc2UoaXMubmEoQ0FOX1BDV19NRUFOKSwgMCwgcGN3cF8xNSksCiAgICAgICAgIGJsb29kX3R5cGUgPSBmYWN0b3IoCiAgICAgICAgICAgY2FzZV93aGVuKAogICAgICAgICAgICAgQ0FOX0FCTyAlaW4lIGMoIkEiLCAiQTEiLCAiQTIiKSB+ICJBIiwKICAgICAgICAgICAgIENBTl9BQk8gJWluJSBjKCJBMUIiLCAiQTJCIikgfiAiQUIiLAogICAgICAgICAgICAgVFJVRSB+IENBTl9BQk8pCiAgICAgICAgICAgKSwKICAgICAgICBwYXlvciA9IGNhc2Vfd2hlbigKICAgICAgICAgIENBTl9QUklNQVJZX1BBWSAlaW4lIGMoMyw0LDEzKSB+ICJNZWRpY2FyZSIsCiAgICAgICAgICBDQU5fUFJJTUFSWV9QQVkgPT0yIH4gIk1lZGljYWlkIiwKICAgICAgICAgIENBTl9QUklNQVJZX1BBWSA9PSAxIH4gIlByaXZhdGUiLAogICAgICAgICAgVFJVRSB+ICJPdGhlciIKICAgICAgICApCiAgKQoKbGlicmFyeSh0YWJsZW9uZSkKY29udF92YXJzIDwtIGMoIkNBTl9BR0VfQVRfTElTVElORyIsICJDQU5fQk1JIiwgCiAgICAgICAgICAgICAgICJDQU5fUFVMTV9BUlRfTUVBTiIsICJDQU5fUENXX01FQU4iLCAiQ2FyZGlhY19JbmRleCIpCgpjYXRfdmFycyA8LSBjKCAic3RhdF9qdXN0IiwgImNmX2x2YWQiLCAKICAgICAgICAgICAgICAgIkdlbmRlciIsIlJhY2UiLCAKICAgICAgICAgICAgICAgIkRpYWdub3NpcyIsICJEaWFiZXRlcyIsICJSZW5hbF9GdW5jdGlvbiIsIAogICAgICAgICAgICAgICAiRnVuY3Rpb25hbF9TdGF0dXMiLCJzZXZlcmVfaW1wYWlybWVudCIsIAogICAgICAgICAgICAgICAiYWN1dGVfbWNzIiwgImx2YWRfY29tcCIsICJwY3dwXzE1IiwgImJsb29kX3R5cGUiLCAicGF5b3IiKQoKCgpDcmVhdGVUYWJsZU9uZSh2YXJzPWNvbnRfdmFycywgZGF0YSA9IGZvcl90YWJsZV9vbmUsIHN0cmF0YSA9ICJnb3RfdHgiKQoKY2F0X3ZhcnNfYnlfdHggPC0gcHJpbnQoQ3JlYXRlQ2F0VGFibGUodmFycyA9IGNhdF92YXJzLCBkYXRhID0gZm9yX3RhYmxlX29uZSwgc3RyYXRhID0gImdvdF90eCIpKQp3cml0ZS5jc3YoY2F0X3ZhcnNfYnlfdHgsICJjYXRfdmFyc19ieV90eC5jc3YiKQoKCmNvbnRfdmFyc19ieV90eCA8LSBwcmludChDcmVhdGVDb250VGFibGUodmFycyA9IGNvbnRfdmFycywgZGF0YSA9IGZvcl90YWJsZV9vbmUsIHN0cmF0YSA9ICJnb3RfdHgiKSkKd3JpdGUuY3N2KGNvbnRfdmFyc19ieV90eCwgImNvbnRfdmFyc19ieV90eC5jc3YiKQoKCgpjYXRfdmFyc18gPC0gcHJpbnQoQ3JlYXRlQ2F0VGFibGUodmFycyA9IGNhdF92YXJzLCBkYXRhID0gZm9yX3RhYmxlX29uZSkpCndyaXRlLmNzdihjYXRfdmFyc18sICJjYXRfdmFyc18uY3N2IikKCgpjb250X3ZhcnNfIDwtIHByaW50KENyZWF0ZUNvbnRUYWJsZSh2YXJzID0gY29udF92YXJzLCBkYXRhID0gZm9yX3RhYmxlX29uZSkpCndyaXRlLmNzdihjb250X3ZhcnNfLCAiY29udF92YXJzXy5jc3YiKQpgYGAKCgoKCg==